दिलचस्प पोस्ट
छवियों में लोगो की मान्यता एक UITextView में लंबवत केंद्र पाठ onClick पर ViewPager ट्रिगर नहीं टंकिनर विजेट में एक सबप्रोसेस का रीयलटाइम आउटपुट दिखाएं सबमिट करने के बजाय जावास्क्रिप्ट का उपयोग करते हुए एएसपी.नेट एमवीसी अजाक्स फ़ॉर्म को कैसे पोस्ट करें पायथन में स्ट्रिंग समानता मेट्रिक्स पायथन द्वारा प्रयुक्त स्ट्रिंग तुलना तकनीक किसी तालिका में सीएसवी फ़ाइल के कुछ कॉलम कॉपी करें ब्राउज़र प्लग-इन कैसे लिखूं? जेनेरिक एचटीएसीईएस www को गैर-www से पुनर्निर्देशित करता है C # TabControl पर टैब हैडर छिपाएं जब, यदि कभी, पाश अनलोल अभी भी उपयोगी है? मैं जावास्क्रिप्ट में फ़ॉर्म को कैसे सबमिट कर सकता हूं? रनटाइम पर डिफ़ॉल्ट app.config बदलें आईएसएलईआरसी ('।') क्यों वापस 1?

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

इसलिए, इसके बाद, मैंने स्पष्ट रूप से एक समर्पित एसटीए थ्रेड पर 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 थ्रेड के संदेश पंप को अन्य धागे से संदेश कैसे पोस्ट करूं?

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

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

ध्यान रखें कि संदेश कतार जो विंडोज़ एक एसटीए धागे के लिए बनाता है पहले से ही एक धागा-सुरक्षित कतार का कार्यान्वयन है। तो बस अपने स्वयं के प्रयोजनों के लिए इसका इस्तेमाल करें यहां एक आधार वर्ग है जिसे आप उपयोग कर सकते हैं, अपने 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);