2010-02-01 10 views
7

मैं COM के लिए नया हूं और एसटीए और एमटीए के बीच अंतर को समझने की कोशिश कर रहा हूं। मैंने एक उदाहरण बनाने की कोशिश की जो दिखाएगा कि COM एसटीए में बनाए गए ऑब्जेक्ट पर कॉल प्रबंधित कर सकता है जो थ्रेड-सुरक्षित नहीं है।ओथ एसटीए धागे से STAThread से बनाए गए COM ऑब्जेक्ट को कॉल नहीं कर सकता

MyCalcServer कक्षा यहां एटीएल सरल वस्तु का उपयोग करके बनाई गई है। इस्तेमाल किया सेटिंग्स this article में के रूप में ही कर रहे हैं:

  • थ्रेडिंग मॉडल: अपार्टमेंट
  • एकत्रीकरण: नहीं
  • इंटरफ़ेस: कस्टम

MyCalcServer COM वस्तु में प्रयोग किया जाता है एक और सी # परियोजना जो है:

class Program 
{ 
    [STAThread] 
    static void Main(string[] args) 
    { 
     MyCOMLib.MyCalcServer instance = new MyCOMLib.MyCalcServer(); 
     string output1; 
     instance.ChangeValue("Gant", out output1); 
     Console.WriteLine(output1); 


     Thread t1 = new Thread(() => 
     { 
      while (true) 
      { 
       string output; 
       instance.ChangeValue("Gant", out output); 
       Console.WriteLine(output); 
      } 
     }); 
     t1.SetApartmentState(ApartmentState.STA); 
     t1.Start(); 

     // : 
     // also has t2 and t3 here with similar code 
     // : 

     t1.Join(); t2.Join(); t3.Join(); 

    } 
} 

हालांकि, यह हमेशा InvalidCastException (E_NOINTERFACE) में टी 1 के कोड के अंदर उठाया जाता है। मैंने बिना किसी सफलता के अपार्टमेंटटास्ट को एमटीए में बदलने की भी कोशिश की है।

Unable to cast COM object of type 'MyCOMLib.MyCalcServerClass' to interface type 'MyCOMLib.IMyCalcServer'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{B005DB8C-7B21-4898-9DEC-CBEBE175BB21}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

क्या कोई कृपया बता सकता है कि मैं यहां क्या गलत कर रहा हूं?

+0

शायद जेआईटी सोचता है कि आप "इंस्टेंस" का उपयोग नहीं कर रहे हैं और इसे जल्दी रिलीज़ करते हैं। मार्शल डालने का प्रयास करें। शामिल होने के बाद ReeleaseComObject (उदाहरण)। – adrianm

+0

@adrianm अभी भी काम नहीं कर रहा है लेकिन इस – Gant

+0

के लिए धन्यवाद MyCOMLib.IMyCalcServer इंस्टेंस = नई MyCOMLib.MyCalcServer() पर पहली पंक्ति को बदलने का प्रयास करें; मुझे लगता है कि केवल इंटरफेस (वर्ग नहीं) धागे के बीच marshalled किया जा सकता है। – adrianm

उत्तर

3

आप स्पष्ट रूप से मुख्य धागे के लिए उदाहरण बनाने के लिए COM से पूछते हैं, तो आप इसे दूसरे थ्रेड पर पास करते हैं। बेशक कुछ परिस्थितियों में इसकी अनुमति है (उदाहरण के लिए MyCalcServer को मल्टीथ्रेड के रूप में घोषित करें)।

लेकिन आपके मामले में ऐसा लगता है कि आपको किसी अन्य धागे के लिए प्रॉक्सी बनाने की आवश्यकता है। नियमित COM क्लाइंट में यह CoMarshalInterThreadInterfaceInStream द्वारा किया जाता है। इसे http://www.codeproject.com/KB/COM/cominterop.aspx

+2

.Net wrapper स्वचालित रूप से धागे के बीच मार्शलिंग करता है (अन्यथा फ़ाइनलाइज़र काम नहीं करेगा)। यदि स्वचालित मार्शल काम नहीं करता है तो त्रुटि E_WRONG_THREAD (8001010E) होगी – adrianm

1

को स्पष्ट करने के लिए एक बड़ा लेख है, मैं इस संकल्प को प्राप्त करने में कामयाब रहा।

जैसा कि मैं COM के लिए नया हूं, मुझे प्रॉक्सी/स्टब के बारे में बहुत कुछ पता नहीं है और उन्हें एसटीए और एसटीए के बीच मार्शलिंग सामानों की आवश्यकता है। एक नई एटीएल परियोजना बनाने के बाद और सुनिश्चित करें कि मेरे पास "प्रॉक्सी/स्टब मर्ज करें" है। समस्या गायब हो गई। Why would I want to merge Proxy/Stub code with my DLL project.

Proxy/stubs providing standard marshaling for your component. In many cases a DLL-based component may not need proxy/stub because it is running in the same context of its client, and this option may seem useless at first. However, COM uses the marshaling process to synchronize access to a component in multi-threaded situations. So, a DLL-based component will need a proxy/stub DLL in at least two cases:

  • It's running a multi-threaded client and needs to pass interface pointer between apartments (STA to STA or MTA to STA).

  • DCOM can provide a surrogate process for a DLL-based component so that it can be accessed in a distributed environment. In this case a proxy/stub is needed to marshal between machines.

By merging the proxy/stub code with your implementation, you don't have to distribute two DLLs, just the one.

मैं @ Dewfy के जवाब का प्रतीक होगा स्वीकार के रूप में के रूप में वह प्रॉक्सी विषय पर कुछ प्रकाश डाला गया है:

मैं इस पृष्ठ उपयोगी से जानकारी मिल।

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