c# सिस्टम.विंडो.फ़ॉर्म। फायरिंग न करें




multithreading com (3)

मैं एक System.Windows.Forms.Timer का उपयोग करना चाहता System.Windows.Forms.Timer यह सुनिश्चित करने के लिए कि किसी इवेंट को एक्सेल ऐडिन के यूआई थ्रेड पर आग लगाना है जो मैं बना रहा हूं। मैं टाइमर का निर्माण निम्नानुसार करता हूं:

private System.Windows.Forms.Timer _timer;

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    Debug.WriteLine("ThisAddIn_Startup:" + Thread.CurrentThread.ManagedThreadId);

    _timer = new System.Windows.Forms.Timer();
    _timer.Tick += new EventHandler(TimerEventHandler);
    _timer.Interval = 500;            
}

टाइमर को एक लाइब्रेरी से कॉम ईवेंट द्वारा निकाल दिया जाता है जो मैं उपयोग कर रहा हूं:

private void OnEvent()
{
    _timer.Start();
}

तब मैं उम्मीद करता _timer कि _timer निम्नलिखित विधि को कॉल करने के लिए कहता है:

public void TimerEventHandler(object sender, EventArgs args)
{
    _timer.Stop();
    Debug.WriteLine("Tick: " + Thread.CurrentThread.ManagedThreadId);                  
}

जैसा कि मैं समझता हूं, जब मैं एडिन थ्रेड में टाइमर बना देता हूं, भले ही इसे किसी अन्य थ्रेड (कॉम इवेंट इस मामले में) से शुरू किया गया हो, यह थ्रेड पर आग लगाना चाहिए, जिस पर इसे बनाया गया था, यानी एडिन थ्रेड। हालांकि, ऐसा नहीं होता है

मैंने अतीत में लिखा RTDServer में इस सटीक तंत्र को लागू किया है ( जैसा केनी केर द्वारा उल्लिखित किया गया है ) और यह अपेक्षित काम करता है लेकिन इस परिदृश्य में _timer कभी भी टिक नहीं करता है।

मैंने भी ऐसे अन्य लेख पढ़े हैं जो एक ही व्यवहार को इंगित करते हैं और समझ नहीं सकते कि मेरे ऐडिन सेटअप के बारे में क्या अलग है?

संपादित करें: ऑनइवेंट () विधि निकाल दी जाती है।


मुझे अभी तक समझ नहीं है कि फॉर्म क्यों। टिमर अपेक्षित रूप से काम नहीं करता है, लेकिन निम्नलिखित उत्कृष्ट लेख में विस्तार से बताया गया है कि कैसे यूआई धागे पर मार्शल काम करें: http://www.codeproject.com/Articles/31971/Understanding- SynchronizationContext-भाग- I


Winforms टाइमर एक नियंत्रण है और इसे किसी प्रपत्र पर डालकर उपयोग किया जाना चाहिए। आप इसे किसी नियंत्रण-संग्रह में कभी नहीं जोड़ें, इसलिए मैं इसे ठीक से काम करने की उम्मीद नहीं करता। दस्तावेज़ीकरण निम्नलिखित कहते हैं

एक टाइमर लागू करता है जो उपयोगकर्ता-निर्धारित अंतराल पर कोई ईवेंट बढ़ाता है। यह टाइमर विंडोज फॉर्म अनुप्रयोगों में उपयोग के लिए अनुकूलित है और एक विंडो में उपयोग किया जाना चाहिए।

इसलिए, मैं सुझाव देता हूं कि आप System.Timers का एक उदाहरण का उपयोग करें। टाईमर क्लास इस कक्षा को कहीं भी इस्तेमाल किया जा सकता है

ध्यान दें कि टिक-इवेंट जो आप ऊपर प्रयोग करते हैं, को सिस्टम। टाइमर। टायमर क्लास में दूसरे नाम से बुलाया जाता है, अर्थात् समाप्त हो जाने वाला कार्यक्रम


मैं शुरू में टिप्पणी के रूप में पोस्ट करने का मतलब था, लेकिन यह बहुत लंबा हो गया

सबसे पहले, आपका थ्रेड संरचना मेरे लिए थोड़ा भ्रमित है, जिस तरह से आपने इसे वर्णित किया है। Debug.WriteLine("OnEvent:" + Thread.CurrentThread.ManagedThreadId) अंदर और हमें अपने डीबग आउटपुट से आपको देखे जाने वाले सभी थ्रेड आईडी को बताएं।

उस ने कहा, नियम हैं:

  • आपको एक STA थ्रेड पर WinForms ' Timer ऑब्जेक्ट बनाना चाहिए, और थ्रेड को स्टार्ट होने से पहले एसटीए के रूप में कॉन्फ़िगर किया जाना चाहिए।

  • यह थ्रेड मुख्य यूआई थ्रेड (जहां आपका मुख्य फॉर्म बनाया गया था) हो सकता है या नहीं हो सकता है, लेकिन यह अभी भी एक संदेश लूप ( अनुप्रयोग के साथ। पम्पिंग संदेश ( उदाहरण ) के अन्य तरीके हैं, लेकिन आम तौर पर आप इसे नेट कोड से नियंत्रित नहीं करते हैं।

  • आप WinForms Timer द्वारा एक ही धागे पर बनाई गई घटनाओं को संभालना चाहिए जो इसे बनाया गया था। यदि आप चाहें तो इन घटनाओं को दूसरे धागे के संदर्भ में 'आगे' कर सकते हैं ( सिंक्रनाइज़ेशन कॉन्टेक्स्ट Send या Post का उपयोग करके), लेकिन मैं इस तरह की जटिलता के किसी भी कारण के बारे में नहीं सोच सकता।

@ मार्टन का जवाब वास्तव में यह करने का सही तरीका बताता है, मेरी राय में