2011-03-28 5 views
7

मैं फ़ाइल कॉपी प्रगति पर अधिसूचनाएं प्राप्त करने के लिए LPPROGRESS_ROUTINE पैरामीटर में पारित होने वाले अज्ञात प्रतिनिधि के साथ एक सी # एप्लिकेशन से CopyFileEx को कॉल कर रहा हूं।क्या मुझे एक अज्ञात प्रतिनिधि को पिन करने की आवश्यकता है?

मेरा सवाल है, क्या अज्ञात प्रतिनिधि को पिन किया जाना चाहिए और क्यों (या क्यों नहीं)।

  1. CopyFileEx अवरुद्ध नहीं किया गया था:

    इसके अलावा, इस सवाल का जवाब परिवर्तन करता है, तो करता है।

  2. यदि मैं एक ऐसे प्रतिनिधि में पास हुआ जो अज्ञात नहीं था।

धन्यवाद!

उत्तर

3

आपको इसे पिन करने की आवश्यकता नहीं है, लेकिन जब तक प्रतिलिपि प्रगति पर है, तब तक आपको इसे जीवित संदर्भ रखने की आवश्यकता है।

अप्रबंधित कोड द्वारा बुलाया जाने वाला थंक पिन किया गया है, लेकिन आपको यह सुनिश्चित करना होगा कि प्रतिनिधि कचरा नहीं है - इसलिए संदर्भ।

+0

यदि अज्ञात विधि एक स्थानीय चर है तो इसे "जीवित" माना जाता है जब तक CopyFileEx वापस नहीं आया है? – SpeksETC

+0

काफी यकीन है कि यह – sehe

+0

@sehe, @SpeksETC: काफी यकीन है, क्या आप हैं? विनिर्देश में ठीक कहां कहता है? Spec की मेरी प्रति विपरीत कहती है, "* कंपाइलर कोड उत्पन्न कर सकता है जिसके परिणामस्वरूप वेरिएबल के भंडारण में इसके युक्त ब्लॉक * से कम जीवनकाल होता है।" –

6

प्रतिनिधि को पिन होने की आवश्यकता नहीं है। एक प्रबंधित ऑब्जेक्ट पिन किया गया यदि यह कचरा कलेक्टर द्वारा स्थानांतरित नहीं किया जा सकता है। यदि मार्शलिंग जानकारी सही है तो मार्शलिंग परत यह सुनिश्चित करेगी कि कुछ इंपीबल के लिए पॉइंटर पास हो जाए।

हालांकि, ऊपर दी गई टिप्पणी जहां आप सुझाव देते हैं कि एक स्थानीय चर प्रतिनिधि जीवित रख सकता है परिवर्तनीय जीवनकाल की गलतफहमी को इंगित करता है। मैं आपको spec पर संदर्भित करता हूं, जिसमें कहा गया है:

स्थानीय चर का वास्तविक जीवनकाल कार्यान्वयन-निर्भर है। उदाहरण के लिए, एक कंपाइलर स्थिर रूप से निर्धारित कर सकता है कि ब्लॉक में एक स्थानीय चर केवल उस ब्लॉक के एक छोटे हिस्से के लिए उपयोग किया जाता है। इस विश्लेषण का उपयोग करके, कंपाइलर कोड उत्पन्न कर सकता है जिसके परिणामस्वरूप परिवर्तनीय भंडारण में इसके युक्त ब्लॉक की तुलना में कम जीवनकाल होता है। भंडारण एक स्थानीय संदर्भ चर से संबोधित किया जाता है कि स्थानीय संदर्भ चर

दूसरे शब्दों में के जीवनकाल की स्वतंत्र रूप से पुन: दावा किया जाता है, अगर आप कहते हैं:

void M() 
{ 
    Foo foo = GetAFoo(); 
    UnmanagedLibrary.DoSomethingToFoo(foo); 
} 

तो घबराना कहने के लिए अनुमति दी है " आप जानते हैं, मैं देखता हूं कि अप्रबंधित कॉल के बाद कभी भी कोई प्रबंधित कोड फिर से foo का उपयोग नहीं करता है; इसलिए मैं उस समय उस ऑब्जेक्ट के भंडारण को पुनः प्राप्त कर सकता हूं, उस समय। जिसका अर्थ यह है कि अप्रबंधित कॉल ऑब्जेक्ट पर काम कर सकती है जब अचानक इसे किसी अन्य धागे पर हटा दिया जाता है।

फू के विनाशक होने पर यह विशेष रूप से बुरा है। अंतिमकरण कोड संभावित रूप से किसी अन्य धागे पर चलाया जाएगा जबकि ऑब्जेक्ट अप्रबंधित लाइब्रेरी द्वारा उपयोग में है, और स्वर्ग केवल जानता है कि किस प्रकार की आपदा होगी।

इस परिस्थिति में आपको प्रबंधित ऑब्जेक्ट को जीवित रखने के लिए KeepAlive का उपयोग करने की आवश्यकता है। स्थानीय चर पर भरोसा न करें; स्थानीय चर विशेष रूप से के रूप में दस्तावेजों को जीवित रखने की गारंटी के रूप में दस्तावेज किए जाते हैं।अधिक जानकारी के लिए

http://msdn.microsoft.com/en-us/library/system.gc.keepalive.aspx देखें।

+0

धन्यवाद एरिक। क्रिस ब्रुमेम कहता है कि "पीइवोक या तो जीसी ढेर के बाहर आपके डेटा को निश्चित मेमोरी में कॉपी करेगा या जीएस ढेर में मेमोरी पिन करेगा और उन बाइट्स को सीधे अप्रबंधित कोड पर बेनकाब करेगा। किसी भी मामले में, आप ' टी को स्पष्ट रूप से पिन करने की आवश्यकता है - जब तक इन बाइट्स तक पहुंच PInvoke कॉल की अवधि के भीतर हो जाती है। "http://blogs.msdn.com/b/cbrumme/archive/2003/05/06/51385 में .aspx? PageIndex = 1 # टिप्पणियां - क्या यह प्रतिनिधियों के लिए भी प्रासंगिक नहीं है? मुझे लगता है कि पिनवोक परत डेटा पिन करती है, जीसी एकत्र नहीं करेगा ... – SpeksETC

+2

@ स्पीक्सईटीसी: जो आलेख आपने विशेष रूप से लिंक किया है, वह बताता है कि आपकी धारणा गलत है। यह कहता है "** हालांकि, आवेदन किसी भी तरह से प्रतिनिधि के जीवनकाल को विस्तारित करने के लिए ज़िम्मेदार नहीं है जब तक अप्रबंधित कोड ** से कोई और कॉल नहीं होगी।" –

+0

@Eric Lippert: क्या वह कथन केवल एसिंक अप्रबंधित कॉल का जिक्र नहीं कर सकता था? टिप्पणियों में वह क्या लिखता है उसे अस्वीकार करने के लिए लगता है कि" अगर अप्रबंधित कैली को केवल कॉल के जीवन के लिए बफर तक पहुंच की आवश्यकता होती है, तो PInvoke मार्शलिंग परत आम तौर पर उस अवधि के लिए पिन करेगी "जब तक कि मार्शलिंग परत अलग-अलग प्रतिनिधियों का व्यवहार नहीं करती ... – SpeksETC

2

निम्नलिखित msdn से दोनों पिनिंग और जीसी की तरह लगता है। CopyFileEx सिंक्रोनस के बाद इस मामले में अनियंत्रित हैं। विशेष रूप से यह कहता है:

"आमतौर पर, आपको प्रतिनिधियों के जीवनकाल के बारे में चिंता करने की आवश्यकता नहीं होगी। जब भी आप अप्रबंधित कोड के प्रतिनिधि को पास कर रहे हों, तो सीएलआर यह सुनिश्चित करेगा कि प्रतिनिधि कॉल के दौरान जिंदा है। हालांकि, अगर देशी कोड कॉल की अवधि से परे पॉइंटर की एक प्रति रखता है और बाद में उस पॉइंटर के माध्यम से कॉल करने का इरादा रखता है, तो आपको कचरा कलेक्टर को प्रतिनिधियों को इकट्ठा करने से स्पष्ट रूप से रोकने के लिए जीसीएचंडल का उपयोग करने की आवश्यकता हो सकती है। "

चूंकि CopyFileEx कॉल के विस्तार से परे फ़ंक्शन में पॉइंटर नहीं रखता है, इसलिए हमें KeepAlive को कॉल करने की आवश्यकता नहीं है।

+0

यह गलत है अगर इस मामले में किसी समस्या में भाग लेने का मौका "बहुत पतला" है। जैसा कि अन्य उत्तरों में बताया गया है, जीसी - एक अन्य धागे पर - * कॉल शुरू होने के बाद * किसी भी बिंदु पर पैरामीटर * के रूप में आपूर्ति किए गए प्रतिनिधि को पुनः प्राप्त कर सकता है। एक अल्पकालिक सिंक्रोनस कॉल के लिए यह "आमतौर पर, आपको चिंता करने की ज़रूरत नहीं है" लेकिन यह सुनिश्चित करने का एकमात्र तरीका * गारंटीकृत * है कि यह काम करेगा यह सुनिश्चित करना है कि जीसी * KeepAlive का उपयोग करके इसे पुनः प्राप्त नहीं करेगा या अन्यथा एक मजबूत संदर्भ बनाए रखना। – user2864740

+0

एक और तरीका रखें: यदि आप सिंक्रोनस कॉल कई मिनट तक फैले हैं तो KeepAlive का उपयोग करके आप आरामदायक * नहीं * महसूस करेंगे? मुझे यकीन है कि इस "आमतौर पर" हमेशा "नहीं" होने से काट और नहीं किया गया है; यहां तक ​​कि कई सेकंड एक सीपीयू के लिए ईन्स और जीसी के लिए बहुत भूख लगी है। आवश्यकतानुसार जीवन भर को नियंत्रित करना सुनिश्चित करें। – user2864740

संबंधित मुद्दे