2011-09-23 16 views
7

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

कोई भी विचार क्यों यह हो रहा है

यहाँ कोड है:।?

private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    DoSomeAsyncWork(); 
} 

private void DoSomeAsyncWork() 
{ 
    System.Windows.Threading.Dispatcher.Run(); 
    Thread thread = new System.Threading.Thread(
     new System.Threading.ThreadStart(
      delegate() 
      { 
       Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => Thread.Sleep(15000))); 
      } 
     )); 
    thread.Start(); 
} 

उत्तर

12

आप लंबे ऑपरेशन को यूआई थ्रेड में वापस डाल रहे हैं। मुझे अपने उदाहरण टिप्पणी करते हैं:

Thread thread = new System.Threading.Thread( 
    new System.Threading.ThreadStart( 
     delegate() { 
      // here we are in the background thread 

      Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
       new Action(() => { 
        // here we are back in the UI thread 
        Thread.Sleep(15000); 
       })); 
     } 
    )); 

तो, अगर आप इस तरह अपने उदाहरण में बदलाव करना चाहिए: दूसरों का उल्लेख किया है

Thread thread = new System.Threading.Thread( 
    new System.Threading.ThreadStart( 
     delegate() { 
      // here we are in the background thread 

      Thread.Sleep(15000); // <-- do the long operation here 

      Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
       new Action(() => { 
        // here we are back in the UI thread 

        // do stuff here that needs to update the UI after the operation finished 
       })); 
     } 
    )); 

रूप में, यह BackgroundWorker वर्ग का उपयोग करना आसान है। यहाँ एक उदाहरण है:

private void DoSomeAsyncWork() 
{ 
    BackgroundWorker bw = new BackgroundWorker(); 

    bw.DoWork += (sender, args) => { 
     // do your lengthy stuff here -- this will happen in a separate thread 
     Thread.Sleep(15000); 
    } 

    bw.RunWorkerCompleted += (sender, args) => { 
     if (args.Error != null) // if an exception occurred during DoWork, 
      MessageBox.Show(args.Error.ToString()); // do your error handling here 

     // do any UI stuff after the long operation here 
     ... 
    } 

    bw.RunWorkerAsync(); // start the background worker 
} 
3

BeginInvoke का उपयोग कर आप वास्तव में यूआई धागे पर कोड को क्रियान्वित कर रहे हैं।

जब आप पृष्ठभूमि कार्यकर्ता थ्रेड से अपना यूआई अपडेट कर रहे हैं तो आपको केवल इसका उपयोग करने की आवश्यकता है। यदि आपके पास बस है:

Thread thread = new System.Threading.Thread(
    new System.Threading.ThreadStart(
     delegate() 
     { 
      Thread.Sleep(15000); 
     } 
    )); 

मुझे लगता है कि यह काम करेगा।

हालांकि, आप "कार्य पूर्ण" ईवेंट नहीं बढ़ा रहे हैं, इसलिए आपके पास धागा समाप्त होने पर (या वास्तव में) कब पता चलने का कोई तरीका नहीं है। BackgroundWorker class पर देखें। यह आपके लिए भारी भारोत्तोलन करता है। आपको बस अपने कोड को DoWork विधि में प्लग करने की आवश्यकता है।

+0

मैं वास्तव में कुछ कोड है कि यह खुद धागा है की आवश्यकता है निष्पादित करने के लिए कोशिश कर रहा हूँ और जब मैं पहली प्रतिनिधि में सीधे कोड की इस पंक्ति जगह (यानी जहां Thread.Sleep है (15000)) मैं एक संदेश प्राप्त करें कि धागा वस्तुओं तक नहीं पहुंच सकता है। यह संदेश है: "कॉलिंग थ्रेड इस ऑब्जेक्ट तक नहीं पहुंच सकता है क्योंकि एक अलग धागा इसका मालिक है।" जाहिर है, यह एक आम मुद्दा है लेकिन पृष्ठभूमि कार्यकर्ता का उपयोग करने के मार्ग के बिना मैं इसे कैसे प्राप्त करने के लिए संघर्ष कर रहा हूं। तो जब मैंने दूसरा नेस्टेड BeginInvoke कॉल जोड़ा तो ऑब्जेक्ट पाया गया लेकिन यूआई अवरुद्ध है। – fin

+0

तो मुझे लगता है कि, जो मैं खोज रहा हूं वह मेरे तर्क को डालने का एक तरीका है जिसे प्रतीत होता है कि एक नए पृष्ठभूमि थ्रेड पर यूआई थ्रेड तक पहुंच की आवश्यकता है। संक्षेप में, यूआई ऑब्जेक्ट्स तक पहुंच प्रदान करें लेकिन पृष्ठभूमि में एक अलग धागे पर चलें? – fin

+0

@ फ़िनबार: आप "पहुंच प्रदान नहीं कर सकते"। यूआई ऑपरेशंस * यूआई थ्रेड में किया जाना चाहिए। हालांकि, आप क्या कर सकते हैं, यूआई ऑपरेशंस को छोटे बिट्स में विभाजित करना, पृष्ठभूमि थ्रेड में बड़ा लूप डालना और लूप के अंदर 'डिस्पैचर.बिनजिन इनवोक (... लघु यूआई ऑपरेशन ...)' को कॉल करना है। इससे यूआई को लंबे समय के बजाय कई बार अवरुद्ध किया जा सकता है। – Heinzi

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