2008-10-03 8 views
8

पर रहने के लिए मजबूर करें मुझे अभी भी एक अलग यूआई थ्रेड में Winforms बनाने के तरीके के बारे में पता चल रहा है, जिस पर मैंने here पर चर्चा की थी।थ्रेड में कोई फॉर्म कैसे खोलें और इसे

इसे समझने की कोशिश में मैंने निम्नलिखित सरल परीक्षण कार्यक्रम लिखा। मैं बस इसे "यूआई थ्रेड" नामक एक अलग थ्रेड पर एक फॉर्म खोलना चाहता हूं और जब तक फॉर्म फॉर्म के साथ बातचीत करने की अनुमति देता है तब तक थ्रेड चल रहा है जब तक कि फॉर्म फॉर्म के साथ बातचीत करने की अनुमति देता है (कताई धोखा दे रहा है)। मैं समझता हूं कि नीचे क्यों विफल रहता है और धागा तुरंत बंद हो जाता है लेकिन मुझे यकीन नहीं है कि इसे ठीक करने के लिए मुझे क्या करना चाहिए।

using System; 
using System.Windows.Forms; 
using System.Threading; 

namespace UIThreadMarshalling { 
    static class Program { 
     [STAThread] 
     static void Main() { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      var tt = new ThreadTest(); 
      ThreadStart ts = new ThreadStart(tt.StartUiThread); 
      Thread t = new Thread(ts); 
      t.Name = "UI Thread"; 
      t.Start(); 
      Thread.Sleep(new TimeSpan(0, 0, 10)); 
     } 

    } 

    public class ThreadTest { 
     Form _form; 
     public ThreadTest() { 
     } 

     public void StartUiThread() { 
      _form = new Form1(); 
      _form.Show(); 
     } 
    } 
} 
+1

हाँ, यह माइक्रोसॉफ्ट सिर्फ एक ही संवाद और एकल धागे के अलावा किसी अन्य चीज़ के माध्यम से ठीक से सोचने में असफल रहा है। जैसा कि नीचे दिए गए समाधान कहते हैं, आप एक अलग संदेश पंप शुरू कर सकते हैं, लेकिन जीयूआई थ्रेड से इसे लॉन्च करने का कोई सुविधाजनक तरीका नहीं है, इसलिए दूसरा फॉर्म गैर-मोडल संवाद के रूप में करने का कोई तरीका नहीं है। –

+0

निष्पक्ष होने के लिए, प्रश्न 4 साल पहले और 12 साल पुरानी तकनीक से संबंधित है :) –

+1

हाँ, मुझे पता है, लेकिन इस तथ्य को अलग करते हुए कि 12 साल पहले भी लोग यह चाहते थे, बिना देखे कि मैं एक बड़ी राशि शर्त लगाऊंगा कि एमएस से किसी भी संशोधित/नए एपीआई में स्थिति बदल नहीं है। –

उत्तर

13

एक नया धागा पर, फोन Application.Run प्रपत्र वस्तु गुजर, इस सूत्र का अपना संदेश पाश चलाने जबकि विंडो खुली है कर देगा।

फिर आप कॉल कर सकते हैं। यूआई थ्रेड समाप्त होने तक अपना मुख्य थ्रेड इंतजार करने के लिए उस धागे पर जुड़ें, या उस धागे को पूरा करने के लिए प्रतीक्षा करने के लिए एक समान चाल का उपयोग करें।

उदाहरण:

public void StartUiThread() 
{ 
    using (Form1 _form = new Form1()) 
    { 
     Application.Run(_form); 
    } 
} 
+0

आह ... मुझे लगता है कि एप्लिकेशन। रून मेरा लापता जिग्स टुकड़ा हो सकता है –

2

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

3
private void button1_Click(object sender, EventArgs e) 
{ 
    var t = new Thread(RunNewForm); 
    t.Start(); 
} 
public static void RunNewForm() 
{ 
    Application.Run(new Form2()); 
} 
+0

हालांकि आप शायद प्रत्येक बटन क्लिक के लिए थ्रेड नहीं करना चाहते हैं, यह समाधान मेरे लिए काम करता है। – styfle

3

मुझे लगता है कि आपकी समस्या को इस विचार के साथ है:

तरह से काम करता है खिड़कियां इस तरह है " 'यूआई धागा' नामक एक अलग थ्रेड पर एक फॉर्म को खोलने के" (plz ध्यान दें विस्टा इनमें से कुछ बदल सकता है वास्तविकताओं):

वहाँ एक महत्वपूर्ण सूत्र "मुख्य थ्रेड" या "यूआई धागा" कहा जाता है। यह धागा वह है जो windows messages को संसाधित करता है, जैसे "हे माउस ने इस पिक्सेल पर क्लिक किया।"

इन संदेशों को एक कतार में जाते हैं, और मुख्य थ्रेड उन्हें प्रक्रियाओं जब यह किसी और कुछ करने में व्यस्त नहीं है।

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

मुख्य धागा स्क्रीन पर यूआई को भी चित्रित करता है, इसलिए लंबे समय से चलने वाला foo() आपके ऐप को पेंटिंग से भी रोक देगा।

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

  1. :

    यह वास्तविकता दो समस्याओं का कारण बनता जब से तुम लंबे समय से चल foo नहीं करना चाहते() सभी उपयोगकर्ता संपर्क को रोकने के लिए, आप एक के लिए रवाना है कि काम जहाज की जरूरत है कार्यकर्ता धागा

  2. मुख्य थ्रेड पर वापस पाने: जब लंबे समय से चल foo() पूरा करती है, तो आप शायद यूआई में कुछ कर रही द्वारा उपयोगकर्ता को सूचित करना चाहते हैं, लेकिन आप उस एक कार्यकर्ता सूत्र में है, तो आप की जरूरत नहीं कर सकते " मुख्य धागे पर वापस जाओ।

तो मेरा मानना ​​है कि उपरोक्त कार्यक्रम में आपकी समस्या बहुत ही सामान्य है: आपका बहुत लक्ष्य गलत है, क्योंकि यह _form.Show() कॉल करने के लिए किसी भी धागा लेकिन पवित्र मुख्य थ्रेड में संभव होना चाहिए नहीं है।

1

मुझे लगता है कि शो के बजाय शोडियलॉग को कॉल करने में मदद मिलेगी। समस्या यह प्रतीत होती है कि शो को कॉल करने के बाद धागा खत्म हो जाता है, उसके बाद फॉर्म को कचरा इकट्ठा किया जाता है। ShowDialog थ्रेड को रोक देगा लेकिन फिर भी फॉर्म-इवेंट चलाएगा ताकि थ्रेड तब तक चल रहा रहे जब तक फॉर्म बंद न हो जाए।

आम तौर पर मैं इसे दूसरी तरफ करता हूं। प्रारंभिक धागे पर फॉर्म चलाएं और जब आप लंबे समय से चल रहे पृष्ठभूमि कार्यों को प्रारंभ करना चाहते हैं तो पृष्ठभूमि थ्रेड प्रारंभ करें।

मैंने आपका अन्य प्रश्न भी पढ़ा लेकिन यह पता नहीं लगा कि आप क्या करने की कोशिश कर रहे हैं। एमवीपी-आर्किटेक्चर के लिए आपको विभिन्न धागे पर अपने व्यावसायिक तर्क चलाने की आवश्यकता नहीं है। मल्टी थ्रेडिंग सही करना मुश्किल है इसलिए अगर मुझे वास्तव में उनकी आवश्यकता होती तो मैं केवल एकाधिक धागे का उपयोग करता।

0

फ़ॉर्म पर शो() को कॉल करने के बजाय फॉर्म पर निष्पादित करने के बजाय और फिर फंक्शन StartUiThread() के भीतर थ्रेड निष्पादन के अंत में बंद करें, तब तक आप थ्रेड को लॉक कर सकते हैं जब तक कि विधि को विधि में बंद नहीं किया जाता आप बस अन्य धागे को लॉक कर रहे हैं। पूर्व:

public void StartUiThread() { 
     _form = new Form1(); 
     _form.ShowDialog(); //Change Show() to ShowDialog() to wait in thread 
    } 

इससे नया धागा संवाद बंद होने तक प्रतीक्षा कर देगा। मुझे नहीं पता कि यह आपकी समस्याओं का समाधान करेगा, लेकिन यह मेरा हल हो गया।