2009-08-05 19 views
18

की COM वस्तु कास्ट करने में असमर्थ मैं निम्नलिखित कोड है:प्रकार अपवाद

public void Test(IMyInterface iInterface) 
{ 
    iInterface.CallMethod (); 
} 

कौन सा ठीक काम करता है। हालांकि, अगर मैं कोड बदलने पिरोया जा सकता:

private IMyInterface myInterface; 
public void Test(IMyInterface iInterface) 
{ 
    myInterface = iInterface; 
    new Thread (new ThreadStart (CallInterfaceMethod)).Start (); 
} 

public void CallInterfaceMethod () 
{ 
    myInterface.CallMethod () 
} 

जब मैं धागा का उपयोग मैं अपवाद प्राप्त करते हैं:

प्रकार की COM वस्तु 'सिस्टम .__ ComObject' कास्ट करने के लिए इंटरफेस करने प्रकार 'IMyInterface' में असमर्थ । यह ऑपरेशन विफल हुआ क्योंकि आईआईडी '{GUID}' के साथ इंटरफ़ेस के लिए COM घटक पर क्वेरी इंटेरफ़ेस कॉल अनुवर्ती त्रुटि के कारण विफल रही: ऐसा कोई इंटरफ़ेस समर्थित नहीं है

लेकिन इंटरफ़ेस को ठीक से समर्थन दिया जाना चाहिए? किसी के पास क्या हो रहा है पर कोई विचार है?

+0

http://blogs.msdn.com/b/oldnewthing/archive/2004/12/13/281910.aspx – EricLaw

उत्तर

20

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

आपके परिदृश्य में वर्णित, कारण यह दूसरे धागे पर विफल रहता है क्योंकि दूसरे धागे में इंटरफ़ेस के लिए प्रकार की जानकारी नहीं है।

आप अपने कोड के लिए निम्न जोड़ने की कोशिश कर सकते हैं:

[ComImport] 
[Guid("23EB4AF8-BE9C-4b49-B3A4-24F4FF657B27")] 
public interface IMyInterface 
{ 
    void CallMethod(); 
} 

मूल रूप से घोषणा से ऊपर .NET फ़्रेमवर्क COM रजिस्ट्री से परंपरागत तकनीक का उपयोग प्रकार की जानकारी लोड और जुड़े प्रकार लायब्रेरी का पता लगाने और जाने के लिए लोड का निर्देश वहां से।

आपको इस समस्या को हल करने में मदद के लिए COM ऑब्जेक्ट को एक थ्रेड (थ्रेड मार्शलिंग को रोकने के लिए) को प्रतिबंधित करना चाहिए।

संक्षेप में, यह त्रुटि प्रकार की जानकारी और थ्रेड मार्शलिंग के आसपास घूमती है। सुनिश्चित करें कि प्रत्येक थ्रेड जो COM ऑब्जेक्ट तक पहुंचना चाहता है, उस स्रोत को स्रोत थ्रेड से ऑब्मरशल करने के लिए प्रासंगिक जानकारी है।

पीएस: यह समस्या .NET 4 में हल हो गई है।0 "टाइप इक्विलिएंन्स" नामक तकनीक का उपयोग करके

+0

उत्तर के लिए धन्यवाद। आपकी व्याख्या समझ में आती है और एमएसडीएन पर कॉम आयात रिपोर्ट को समझना भी समझ में आता है। चीयर्स। – Kyle

+0

यह मेरी खुशी है :) मैंने पहले इस मुद्दे में भाग लिया है और यह कोशिश करने और हल करने के लिए एक दुःस्वप्न था, जब तक कि लाइटबुल बंद नहीं हुआ और मैंने COM वस्तु को उस धागे से खपत कर लिया जो इसे बनाया गया था। –

+1

[+1] बहुत बहुत धन्यवाद! मेरे लिए त्रुटि यह थी कि [STAThread] गायब था। इस सवाल और उत्तर ने मुझे थ्रेडिंग समस्या पढ़ने के बाद इसे ढूंढने का नेतृत्व किया। – Marc

-1

ठीक है, एक के लिए, आप किसी ऑब्जेक्ट को लॉक किए बिना क्रॉस-थ्रेड कॉल कर रहे हैं, यह स्वचालित रूप से कुछ समस्याएं पैदा करेगा। आपका कोड अधिक तरह दिखना चाहिए:

private IMyInterface myInterface; 
private static readonly object _myObjectLock = new object(); 

public void Test(IMyInterface iInterface) 
{ 
    myInterface = iInterface; 
    new Thread (new ThreadStart (CallInterfaceMethod)).Start (); 
} 

public void CallInterfaceMethod () 
{ 
    lock(_myObjectLock) 
    { 
     myInterface.CallMethod (); 
    } 
} 

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

सच में, मुझे नहीं लगता कि मैं इस तरीके से इस विधि को कॉल करने के लिए पहुंचूंगा, इस तरह से ऐसा करने में बहुत अधिक जोखिम हैं। क्या आपने ParameterizedThreadStart का उपयोग करके विचार किया है और ऑब्जेक्ट को इस तरह से गुजर रहा है? आपको अभी भी क्रॉस-थ्रेड ऑपरेशंस के लिए अपनी ऑब्जेक्ट्स को सुरक्षित रूप से लॉक करने की आवश्यकता होगी, लेकिन यह सुरक्षित होगा।

इसके अलावा, यह सुनिश्चित करने के लिए जांचें कि आपकी "myInterface" कक्षा अभी भी "CallMethod()" विधि को कॉल कर सकती है। इंटरफ़ेस में कोई कार्यान्वयन नहीं होता है, जब आप "myInterface = iInterface" सेट करते हैं तो आप समस्याओं में भाग ले सकते हैं।

+0

से आप जवाब के लिए है, लेकिन का उपयोग कर ParameterizedThreadStart या तो (के साथ या लॉक के बिना) काम नहीं करता। मैंने यह भी जांच लिया है, मेरा इंटरफ़ेस अभी भी सेट होने के बाद "CallMethod" कर सकता है (myInterface = iInterface)। – Kyle

+0

इस उत्तर में गलत जानकारी के दो बिट हैं: ** 1। ** क्रॉस-थ्रेड ऑब्जेक्ट एक्सेस * हमेशा * स्वचालित रूप से समस्याओं का कारण नहीं बनता है। उदाहरण के लिए, केवल पढ़ने-योग्य पहुंच के साथ लॉकिंग आवश्यक नहीं होनी चाहिए। ** 2। ** अंतिम पैराग्राफ के बारे में, आप ऑब्जेक्ट्स के रूप में इंटरफेस को पास नहीं कर सकते हैं, इसलिए यदि आप किसी इंटरफ़ेस (स्थिर) प्रकार के साथ एक चर के लिए गैर-शून्य ऑब्जेक्ट असाइन करते हैं, और कोड संकलित करते हैं, तो ये सभी विधियां कर सकती हैं बुलाया जाए। किसी अन्य कार्यान्वयन प्रकार के लिए किसी प्रकार का मुखौटा के रूप में स्थिर प्रकार (इंटरफ़ेस) के बारे में सोचें। – stakx

3

मुझे सलाह मिली और इससे मेरी मदद मिली!

लाइन [STAThread] मुख्य थ्रेड (Program.cs) में खोजें और इसे [MTAThread] में बदलें।

+0

यह एक आकर्षण की तरह काम किया। क्या आप परिवर्तन की व्याख्या कर सकते हैं? –

0

मैं एक सी # अनुप्रयोग विकसित कर रहा हूं जो COM इंटरफेस के माध्यम से 7-ज़िप का उपयोग करता है। मैं इस अजीब चीज में भाग गया जहां मैं एक उदाहरण में एक कार्यकर्ता थ्रेड से अभिलेखागार निकालने में सक्षम था, लेकिन दूसरा नहीं, यह एक ही अपवाद प्राप्त कर रहा था।

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

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