2009-02-08 11 views
33

मुझे एमएसडीएन को इंगित किए बिना, क्या इनमें से प्रत्येक के उद्देश्य और उन्हें उपयोग करने के उद्देश्य से कोई संक्षिप्त, स्पष्ट स्पष्टीकरण दे सकता है। (IntPtr, SafeHandle और HandleRef)इंटप्राट, सेफहैंडल और हैंडलरफ - समझाया गया

+1

एमएसडीएन के साथ क्या गलत है? –

+8

कुछ भी नहीं। यह सुनिश्चित करने के लिए कि मैं उन्हें सही तरीके से उपयोग कर रहा हूं, बस प्रत्येक का एक संक्षिप्त सारांश ढूंढ रहा हूं। अगर मैं एमएसडीएन और अन्य लोगों के विवरण पढ़ता हूं तो मुझे बेहतर लगता है कि मैं जो कर रहा हूं वह सही है। – user62572

उत्तर

46

IntPtr केवल एक साधारण पूर्णांक-आधारित संरचना है जो एक सूचक (यानी, 32-बिट सिस्टम पर 32 बिट आकार, 64-बिट सिस्टम पर 64-बिट आकार) रख सकता है।

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

HandleRef यह सुनिश्चित करने का एक तरीका है कि एक अप्रबंधित हैंडल जीसीड नहीं है जब आप पी/इनवॉक कॉल के बीच में हों। HandleRef जैसे कुछ के बिना, यदि आपका प्रबंधित कोड पी/इनवॉक कॉल के बाद हैंडल के साथ कुछ भी नहीं करता है, तो जीसी पी/इनवॉक कॉल के दौरान चलाया गया था, तो यह महसूस नहीं होगा कि हैंडल अभी भी उपयोग में है और जीसी । मुझे कल्पना है (लेकिन मुझे यकीन नहीं है और मैंने नहीं देखा है) SafeHandle encapsulated हैंडल के प्रबंधन के हिस्से के रूप में HandleRef का उपयोग कर सकते हैं।

HWnd a = new HWnd(); 
IntPtr h = a.Handle; 
// a is no longer needed and thus can be GC'ed 
B.SendMessage(h, ...); 

समस्या यह है कि जब "एक" निपटान किया जाता है, यह संभाल बंद हो जाएगा:

+13

मामूली सुधार। जब आप PInvoke के दौरान * प्रबंधित * ऑब्जेक्ट GC'ed नहीं चाहते हैं तो HandleRef का उपयोग करें। उदाहरण कक्षा एचडब्ल्यूएनडी {सार्वजनिक IntPtr हैंडल; } एचडब्ल्यूएनडी = = नया एचडब्ल्यूएनडी(); बी। सैंडमेसेज (ए। हैंडल, ...); <- PInvoke बी.एंडेंडमेसेज (नया हैंडलरफ (ए, ए। हैंडल)) में जीसीड किया जा सकता है <- अब पीएनवोक –

+3

में जीसीड नहीं किया जा सकता है एक और अतिरिक्त: 'सेफहैंडल' में संदर्भ गणना शामिल है हैंडल रीसाइक्लिंग हमलों को रोकने के लिए। –

+0

क्या कोई भी सुरक्षित हैंडलफ्रेंड का उपयोग कर सकता है?या कम से कम एक समान तंत्र है? – Assimilater

16
HWnd a = new HWnd(); 
B.SendMessage(a.Handle, ...); 

इस मान लिया जाये कि "एक" कार्यक्रम में, इस के बराबर है करने के लिए केवल संदर्भ है। यदि यह SendMessage पर कॉल के पहले या उसके दौरान होता है, तो हैंडल अमान्य होगा।

हैंडलरफ एच के साथ कार्यक्रम के पहले किए गए कचरे से "ए" को रोकता है।

1

यह SafeHandle की तरह लग रहा HandleRef के KeepAlive व्यवहार कैसे शामिल करता है: Project Roslyn SafeHandle.cs http://referencesource.microsoft.com/#mscorlib/system/runtime/interopservices/safehandle.cs,743afbddafaea263

/* 
    Problems addressed by the SafeHandle class: 
    1) Critical finalization - ensure we never leak OS resources in SQL. Done 
    without running truly arbitrary & unbounded amounts of managed code. 
    2) Reduced graph promotion - during finalization, keep object graph small 
    3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread ---- (HandleRef) 
<...> 
*/ 

लेकिन मैं यकीन नहीं है, यह keepalive व्यवहार की तरह दिखता है केवल निर्माता को गलत मूल्य प्रदान करके प्राप्त किया जा सकता जो केवल ऑब्जेक्ट को अंतिम रूप देने योग्य नहीं है, इसलिए आपको उस मामले में संसाधन रिसाव को रोकने के लिए सेफहैंडल के निपटान() मैनुअल को कॉल करना होगा, क्या मैं सही हूँ? कोई स्रोत कोड की व्याख्या कर सकते, क्या

private extern void InternalDispose(); 
private extern void InternalFinalize(); 

है?

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