दिलचस्प पोस्ट
सूची :: आकार () वास्तव में हे (एन) है? एंड्रॉइड में छवि के कुछ भाग को कैसे धुँधला जा सकता है? एकल पृष्ठ एप्लिकेशन – आंशिक दृश्य के आधार पर गतिशील रूप से लोड जेएस फ़ाइल MFMailComposeViewController का उपयोग करके ईमेल शरीर में एक छवि कैसे जोड़ें स्प्रिंग रेस्टटेमप्लेट – अनुरोधों / प्रतिक्रियाओं के पूर्ण डिबगिंग / लॉगिंग को सक्षम कैसे करें? अजाक्स बाइनरी रिस्पांस जावा: जेपीनेल पृष्ठभूमि स्केलिंग नहीं है INNER JOIN स्थिति में एक 'OR' क्या एक बुरा विचार है? HttpWebRequest और HttpWebResponse से एचटीपीटी स्थिति कोड संख्या (200, 301, 404, आदि) प्राप्त करना नक्शे में मान के रूप में स्ट्रेट को मान सेट करते समय मुझे "असाइन नहीं किया जा सकता" त्रुटि क्यों मिलती है? उपयोगकर्ता नाम और पासवर्ड के साथ नेटवर्क ड्राइव से कनेक्ट करें फॉर्म_लोड () 'इवेंट' या ओवरराइड ऑनलोड () XSLT / XPath में वर्तमान नोड बनाम संदर्भ नोड? Android getDefaultSharedPreferences मैं आईआईएस के लिए आईआईएस को एचटीएमएल 5 मोड में एन्जिलरजेएस एप्लीकेशन में लिखने के लिए कैसे कॉन्फ़िगर करूं?

संदेश पंप चलने वाले एसटीए थ्रेड में संदेश कैसे पोस्ट करें?

इसलिए, इसके बाद, मैंने स्पष्ट रूप से एक समर्पित एसटीए थ्रेड पर COM ऑब्जेक्ट को इन्स्तांत करने का निर्णय लिया। प्रयोगों से पता चला कि COM ऑब्जेक्ट को एक संदेश पंप की आवश्यकता होती है, जिसे मैंने Application.Run() को कॉल करके बनाया था।

 private MyComObj _myComObj; // Called from Main(): Thread myStaThread = new Thread(() => { _myComObj = new MyComObj(); _myComObj.SomethingHappenedEvent += OnSomthingHappened; Application.Run(); }); myStaThread.SetApartmentState(ApartmentState.STA); myStaThread.Start(); 

मैं STA थ्रेड के संदेश पंप को अन्य धागे से संदेश कैसे पोस्ट करूं?

नोट: संक्षिप्तता के लिए मैंने इस प्रश्न को भारी रूप से संपादित किया @ सेटी के उत्तर के कुछ हिस्से अब असंबंधित हैं, लेकिन वे मूल प्रश्न के लिए थे।

Solutions Collecting From Web of "संदेश पंप चलने वाले एसटीए थ्रेड में संदेश कैसे पोस्ट करें?"

ध्यान रखें कि संदेश कतार जो विंडोज़ एक एसटीए धागे के लिए बनाता है पहले से ही एक धागा-सुरक्षित कतार का कार्यान्वयन है। तो बस अपने स्वयं के प्रयोजनों के लिए इसका इस्तेमाल करें यहां एक आधार वर्ग है जिसे आप उपयोग कर सकते हैं, अपने COM ऑब्जेक्ट को शामिल करने के लिए स्वयं प्राप्त करें। प्रारंभिक विधि () को ओवरराइड करें, जैसे ही थ्रेड कोड निष्पादित करने के लिए तैयार है, इसे जल्द ही बुलाया जाएगा। आधार कॉल करने के लिए मत भूलना। अपने ओवरराइड में प्रारंभ करें ()।

यह आप उस धागे पर कोड को चलाने के लिए चाहते हैं तो BeginInvoke का उपयोग करें या विधियों को खोलें, जैसे आप नियंत्रण के लिए करेंगे। आरंभ करें / आमंत्रित करें या डिस्पैचर। थ्रेड को बंद करने के लिए अपनी विस्थापन () विधि को कॉल करें, यह वैकल्पिक है सावधान रहें कि जब आप 100% सुनिश्चित करते हैं कि सभी COM ऑब्जेक्ट को अंतिम रूप दिया जाता है तो यह केवल सुरक्षित होता है। चूंकि आपको आमतौर पर यह गारंटी नहीं होती है, इसलिए यह बेहतर नहीं है कि आप ऐसा नहीं करते।

 using System; using System.Threading; using System.Windows.Forms; class STAThread : IDisposable { public STAThread() { using (mre = new ManualResetEvent(false)) { thread = new Thread(() => { Application.Idle += Initialize; Application.Run(); }); thread.IsBackground = true; thread.SetApartmentState(ApartmentState.STA); thread.Start(); mre.WaitOne(); } } public void BeginInvoke(Delegate dlg, params Object[] args) { if (ctx == null) throw new ObjectDisposedException("STAThread"); ctx.Post((_) => dlg.DynamicInvoke(args), null); } public object Invoke(Delegate dlg, params Object[] args) { if (ctx == null) throw new ObjectDisposedException("STAThread"); object result = null; ctx.Send((_) => result = dlg.DynamicInvoke(args), null); return result; } protected virtual void Initialize(object sender, EventArgs e) { ctx = SynchronizationContext.Current; mre.Set(); Application.Idle -= Initialize; } public void Dispose() { if (ctx != null) { ctx.Send((_) => Application.ExitThread(), null); ctx = null; } } private Thread thread; private SynchronizationContext ctx; private ManualResetEvent mre; } 

क्या संदेश पंप को शुरू करने का कोई तरीका है, जिससे ब्लॉक न हो?

नहीं। संदेश कतार का मुद्दा यह है कि उसे थ्रेड के निष्पादन का उपभोग करने की आवश्यकता है। एक संदेश कतार, कार्यान्वयन में है, आपके समान दिखने वाला है:

 while(!_stopped) { var job = _myBlockingCollection.Take(); // <-- blocks until some job is available ProcessJob(job); } 

यह एक संदेश लूप है आप जो करने की कोशिश कर रहे हैं, उसी थ्रेड में दो भिन्न संदेश लूप चलाए जा रहे हैं। आप वास्तव में ऐसा नहीं कर सकते (और दोनों कतार पम्पिंग कर रहे हैं, एक कतार आवश्यक होगा, दूसरे के चलने के दौरान रोकें), यह सिर्फ समझ में नहीं आता है।

एक ही धागे पर दूसरा संदेश लूप बनाने के बजाय आपको क्या करने की आवश्यकता है, आपके वर्तमान कतार में संदेश भेजते हैं। ऐसा करने का एक तरीका एक SynchronizationContext के उपयोग के माध्यम से है एक समस्या यह है कि कोई ऐसी घटना नहीं है जिसे संदेश पंप में Run उस अधिभार के साथ एक विधि को निष्पादित करने के लिए लगाया जा सकता है। हमें एक Form दिखाने की आवश्यकता होगी ताकि हम Shown घटना में हुक कर सकें (जिस बिंदु पर हम उसे छिपा सकते हैं)। तब हम SynchronizationContext कंटबॉक्स को हड़प कर रख सकते हैं और इसे कहीं और संग्रहीत कर सकते हैं, जिससे हमें संदेश पंप में संदेशों को पोस्ट करने के लिए इसका उपयोग करने की अनुमति मिलती है:

 private static SynchronizationContext context; public static void SendMessage(Action action) { context.Post(s => action(), null); } 

 Form blankForm = new Form(); blankForm.Size = new Size(0, 0); blankForm.Shown += (s, e) => { blankForm.Hide(); context = SynchronizationContext.Current; }; Application.Run(blankForm);