WPF

2010-06-23 10 views
9

में पृष्ठभूमि कार्यकर्ता के साथ मुख्य ऐप के लिए एक संदेशबॉक्स को रोकना एक WPF ऐप में, मैं समय-समय पर सर्वर पर एक शर्त की जांच करने के लिए पृष्ठभूमिवर्कर का उपयोग कर रहा हूं। हालांकि यह ठीक काम करता है, मैं चेकबॉक्स के दौरान कुछ विफल होने पर उपयोगकर्ताओं को नोटिस करने के लिए एक संदेश बॉक्स पॉप करना चाहता हूं।WPF

यहाँ मैं क्या है:

public static void StartWorker() 
{ 
    worker = new BackgroundWorker(); 

    worker.DoWork += DoSomeWork; 
    worker.RunWorkerAsync(); 
} 

private static void DoSomeWork(object sender, DoWorkEventArgs e) 
{ 
    while (!worker.CancellationPending) 
    { 
     Thread.Sleep(5000); 

     var isOkay = CheckCondition(); 

     if(!isOkay) 
      MessageBox.Show("I should block the main window");     
    } 
} 

लेकिन इस MessageBox मुख्य विंडो ब्लॉक नहीं करता। मैं अभी भी अपने डब्ल्यूपीएफ ऐप पर क्लिक कर सकता हूं और मैसेजबॉक्स के साथ मुझे जो भी पसंद है उसे बदल सकता हूं।

मैं इसे कैसे हल करूं? धन्यवाद,


संपादित करें:

public static void StartWorker() 
{ 
    worker = new BackgroundWorker(); 

    worker.DoWork += DoSomeWork; 
    worker.ProgressChanged += ShowWarning; 
    worker.RunWorkerAsync(); 
} 

private static void DoSomeWork(object sender, DoWorkEventArgs e) 
{ 
    while (!worker.CancellationPending) 
    { 
     Thread.Sleep(5000); 

     var isOkay = CheckCondition(); 

     if(!isOkay) 
      worker.ReportProgress(1);     
    } 
} 

private static void ShowWarning(object sender, ProgressChangedEventArgs e) 
{ 
    MessageBox.Show("I block the main window"); 
} 

उत्तर

6

कॉल ReportProgress और MessageBox.Show को this पारित:

के लिए, इस मैं क्या कर समाप्त हो गया है।

10

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

इसी तरह, संदेशबॉक्स केवल उसी संदेश कतार से संबंधित विंडो को अक्षम करता है। और इस प्रकार आपके मुख्य धागे द्वारा बनाई गई विंडो को अवरुद्ध नहीं करेगा।

यूआई थ्रेड संदेश बॉक्स को प्रदर्शित करके अपनी समस्या को ठीक करें। Dispatcher का उपयोग करें। या तो ReportProgress या RunWorker पूर्ण घटनाओं का लाभ उठाएं या लाभ उठाएं। घटनाओं की तरह ध्वनि नहीं है यहाँ उचित हैं।

+0

धन्यवाद, मुझे लगता है कि इस सूत्र से संबंधित है के लिए किया था, लेकिन मैं पता नहीं है कि यह कैसे हल करना है। "ReportProgess" या "RunWorkerCompleted" का उपयोग करना सहज नहीं था, लेकिन स्पष्टीकरण पढ़ने से बहुत अधिक इंद्रियां होती हैं। –

3

this.Invoke((Func<DialogResult>)(() => MessageBox.Show("I should block the main window"))); 

साथ

MessageBox.Show("I should block the main window"); 

बदलें कि संदेश बॉक्स मुख्य थ्रेड पर होना करने के लिए कारण होगा और जब तक यह एक प्रतिक्रिया मिलती है यूआई के इस्तेमाल के सभी रोकेंगे। एक अतिरिक्त बोनस के रूप में। इन्वोक एक ऑब्जेक्ट वापस कर देगा जिसे डायलॉग रिसेट में डाला जा सकता है।

+0

मैं भी इस समाधान को आजमा देना चाहता हूं, लेकिन मैं इसे संकलित करने के लिए नहीं मिल सकता। मैं इसे एक सामान्य वर्ग (नियंत्रण नहीं) से बुला रहा हूं और इसमें इस पर आमंत्रण नहीं है। मैंने "Dispatcher.CurrentDispatcher.Invoke()" भी कोशिश की लेकिन यह फनक नहीं लेता है जिसे –

+0

सुझाया गया था, मुझे लगता है कि इसे फ़ॉर्म से बुलाया जा रहा था। इस विधि को करने में सक्षम होने के लिए आपको कक्षा को मूल रूप से संदर्भित करने और _ParentForm.Invoke (...) का उपयोग करने की आवश्यकता होगी, ऐसा करने का एक और तरीका हो सकता है लेकिन मुझे शीर्ष के किसी भी हिस्से को नहीं पता मेरा सिर। –

+0

यह एक फॉर्म –

2

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

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

1

मैं इसे इस तरह से संशोधित और मेरे लिए ठीक काम किया

return Application.Current.Dispatcher.Invoke(() => MessageBox.Show(messageBoxText, caption, button, icon)); 
+1

शौडल उत्तर के उत्तर पर एक टिप्पणी हो। – user3595247