2012-03-07 23 views
32

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

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

यहाँ मेरी कार्यक्रम के एक बहुत ही सरल संरचना:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     Initialize Component(); 
    } 

    private void startCalc(object sender, RoutedEventArgs e) 
    { 
     inputValues input = new inputValues(); 

     calcClass calculations = new calcClass(); 

     try 
     { 
      input.pota = Convert.ToDouble(aVar.Text); 
      input.potb = Convert.ToDouble(bVar.Text); 
      input.potc = Convert.ToDouble(cVar.Text); 
      input.potd = Convert.ToDouble(dVar.Text); 
      input.potf = Convert.ToDouble(fVar.Text); 
      input.potA = Convert.ToDouble(AVar.Text); 
      input.potB = Convert.ToDouble(BVar.Text); 
      input.initStart = Convert.ToDouble(initStart.Text); 
      input.initEnd = Convert.ToDouble(initEnd.Text); 
      input.inita = Convert.ToDouble(inita.Text); 
      input.initb = Convert.ToDouble(initb.Text); 
      input.initc = Convert.ToDouble(initb.Text); 
     } 
     catch 
     { 
      MessageBox.Show("Some input values are not of the expected Type.", "Wrong Input", MessageBoxButton.OK, MessageBoxImage.Error); 
     } 
     Thread calcthread = new Thread(new ParameterizedThreadStart(calculations.testMethod); 
     calcthread.Start(input); 
    } 

public class inputValues 
{ 
    public double pota, potb, potc, potd, potf, potA, potB; 
    public double initStart, initEnd, inita, initb, initc; 
} 

public class calcClass 
{ 
    public void testmethod(inputValues input) 
    { 
     Thread.CurrentThread.Priority = ThreadPriority.Lowest; 
     int i; 
     //the input object will be used somehow, but that doesn't matter for my problem 
     for (i = 0; i < 1000; i++) 
     { 
      Thread.Sleep(10); 
     } 
    } 
} 

मैं अगर किसी को कैसे testmethod अंदर से यूआई अद्यतन करने के लिए इसे आसानी से समझा था बहुत आभारी होंगे। चूंकि मैं सी # और ऑब्जेक्ट उन्मुख प्रोग्रामिंग के लिए नया हूं, इसलिए बहुत जटिल उत्तर मैं शायद समझ नहीं पाएगा, हालांकि मैं अपना सर्वश्रेष्ठ प्रदर्शन करूंगा।

अगर किसी के पास सामान्य रूप से बेहतर विचार है (शायद पृष्ठभूमि कार्यकर्ता या कुछ और का उपयोग कर) तो मैं इसे देखने के लिए खुला हूं।

+2

यह एक पुराना और उत्तर दिया गया सवाल है, लेकिन इतना लोकप्रिय है कि मैं इसे किसी भी व्यक्ति के लिए थ्रेड के बीच एक बहुत ही सरल 'प्रगति संवाददाता' को लागू करने के लिए साझा करता हूं। वर्ग प्रगति का उपयोग करें। स्टीफन क्लेरी द्वारा यहां एक अच्छे लेख में कार्यान्वयन का विवरण दिया गया है: http://blog.stephencleary.com/2012/02/reporting-progress-from-async-tasks.html। – SeanOB

उत्तर

52

सबसे पहले आपको Dispatcher.Invoke का उपयोग किसी अन्य थ्रेड से UI को बदलने और किसी अन्य वर्ग से करने के लिए करने की आवश्यकता है, तो आप ईवेंट का उपयोग कर सकते हैं।
तो फिर तुम उस घटना (रों) मुख्य वर्ग में रजिस्टर और यूआई में परिवर्तन प्रेषण और गणना के वर्ग में आप घटना फेंक जब तुम यूआई सूचित करना चाहते हैं कर सकते हैं:

class MainWindow 
{ 
    startCalc() 
    { 
     //your code 
     CalcClass calc = new CalcClass(); 
     calc.ProgressUpdate += (s, e) => { 
      Dispatcher.Invoke((Action)delegate() { /* update UI */ }); 
     }; 
     Thread calcthread = new Thread(new ParameterizedThreadStart(calc.testMethod)); 
     calcthread.Start(input); 
    } 
} 

class CalcClass 
{ 
    public event EventHandler ProgressUpdate; 

    public void testMethod(object input) 
    { 
     //part 1 
     if(ProgressUpdate != null) 
      ProgressUpdate(this, new YourEventArgs(status)); 
     //part 2 
    } 
} 

अद्यतन:
जैसा कि ऐसा लगता है कि यह अभी भी अक्सर एक बार देखा गया प्रश्न और उत्तर है, मैं इस उत्तर को अपडेट करना चाहता हूं कि मैं इसे कैसे करूं (.NET 4 के साथ।

class MainWindow 
{ 
    Task calcTask = null; 

    void buttonStartCalc_Clicked(object sender, EventArgs e) { StartCalc(); } // #1 
    async void buttonDoCalc_Clicked(object sender, EventArgs e) // #2 
    { 
     await CalcAsync(); // #2 
    } 

    void StartCalc() 
    { 
     var calc = PrepareCalc(); 
     calcTask = Task.Run(() => calc.TestMethod(input)); // #3 
    } 
    Task CalcAsync() 
    { 
     var calc = PrepareCalc(); 
     return Task.Run(() => calc.TestMethod(input)); // #4 
    } 
    CalcClass PrepareCalc() 
    { 
     //your code 
     var calc = new CalcClass(); 
     calc.ProgressUpdate += (s, e) => Dispatcher.Invoke((Action)delegate() 
      { 
       // update UI 
      }); 
     return calc; 
    } 
} 

class CalcClass 
{ 
    public event EventHandler<EventArgs<YourStatus>> ProgressUpdate; // #5 

    public TestMethod(InputValues input) 
    { 
     //part 1 
     ProgressUpdate.Raise(this, status); // #6 - status is of type YourStatus 
     //part 2 
    } 
} 

static class EventExtensions 
{ 
    public static void Raise<T>(this EventHandler<EventArgs<T>> theEvent, 
           object sender, T args) 
    { 
     if (theEvent != null) 
      theEvent(sender, new EventArgs<T>(args)); 
    } 
} 

@ 1) कैसे "तुल्यकालिक" गणना शुरू करने और उन्हें पृष्ठभूमि

@ 2) में चला कैसे शुरू करने के लिए करने के लिए: - 5) इस थोड़ी देर के रूप में मैं कुछ अलग अलग संभावनाएं दिखाएगा यह "एसिंक्रोनस" और "इसका इंतजार" करता है: यहां गणना को वापस करने से पहले निष्पादित और पूरा किया जाता है, लेकिन async/await की वजह से यूआई अवरुद्ध नहीं है (बीटीडब्ल्यू: ऐसे ईवेंट हैंडलर async void के एकमात्र वैध उपयोग हैं ईवेंट हैंडलर को void वापस करना होगा - अन्य सभी मामलों में async Task का उपयोग करें)

@ 3) नए Thread के बजाय अब हम Task का उपयोग करते हैं। बाद में इसे (सफल) पूरा करने की जांच करने में सक्षम होने के बाद हम इसे वैश्विक calcTask सदस्य में सहेजते हैं। पृष्ठभूमि में यह एक नया धागा भी शुरू करता है और वहां कार्रवाई चलाता है, लेकिन इसे संभालना बहुत आसान है और इसके कुछ अन्य लाभ भी हैं।

@ 4) यहां हम भी कार्रवाई शुरू करते हैं, लेकिन इस बार हम कार्य वापस कर देते हैं, इसलिए "async ईवेंट हैंडलर" "इसका इंतजार कर सकता है"। हम async Task CalcAsync() और फिर await Task.Run(() => calc.TestMethod(input)).ConfigureAwait(false); (FYI: ConfigureAwait(false) डेडलॉक्स से बचने के लिए भी बना सकते हैं, यदि आप async/await का उपयोग करते हैं तो आपको इसे पढ़ना चाहिए क्योंकि यह यहां व्याख्या करने के लिए बहुत कुछ होगा) जिसके परिणामस्वरूप वही वर्कफ़्लो होगा, लेकिन जैसा कि Task.Run एकमात्र "प्रतीक्षा करने योग्य ऑपरेशन" है और आखिरी है कि हम केवल कार्य को वापस कर सकते हैं और एक संदर्भ स्विच सहेज सकते हैं, जो कुछ निष्पादन समय बचाता है।

@ 5) यहाँ मैं अब एक "दृढ़ता से टाइप किया सामान्य घटना" उपयोग करती हैं इसलिए हम आसानी से

@ 6 पारित कर सकते हैं और प्राप्त हमारे "स्थिति वस्तु") यहाँ मैं आसानी से विस्तार नीचे परिभाषित है, जो (एक तरफ का उपयोग उपयोग के) पुराने उदाहरण में संभावित दौड़ की स्थिति को हल करें। ऐसा हो सकता है कि if-चेक के बाद घटना null मिली, लेकिन कॉल से पहले यदि ईवेंट हैंडलर को उस पल में किसी अन्य थ्रेड में हटा दिया गया था। यह यहां नहीं हो सकता है, क्योंकि एक्सटेंशन को ईवेंट प्रतिनिधि की "प्रतिलिपि" मिलती है और उसी स्थिति में हैंडलर अभी भी Raise विधि के अंदर पंजीकृत है।

+0

तेज उत्तर के लिए धन्यवाद, मैंने इसे अपने कोड में जोड़ा, हालांकि कैल्क क्लास में मुझे "प्रोग्रेसअपडेट" के साथ समस्याएं मिलती हैं, कक्षा इसे पहचान नहीं पाती है। क्या मुझे ऐसा करने के लिए कुछ भी शामिल करना है? अब तक मैंने अभी "सिस्टम का उपयोग कर। थ्रेडिंग" जोड़ा है। – phil13131

+0

हां, मुझे निम्न त्रुटि संदेश मिलता है: त्रुटि अमान्य टोकन ';' कक्षा, संरचना, या इंटरफ़ेस सदस्य घोषणा – phil13131

+0

में मैंने कोड के रूप में बताए गए कोड का उपयोग किया है और उस पंक्ति पर त्रुटि प्राप्त करें जहां "सार्वजनिक घटना प्रगति अद्यतन;" घोषित किया गया है – phil13131

0

शुक्र है, माइक्रोसॉफ्ट कि उस पर एक Dispatcher WPF में :)

हर Control पता लगा, एक प्रगति बार, बटन, प्रपत्र, आदि जैसे है मिला है। आप Dispatcher एक Action दे सकते हैं जिसे निष्पादित करने की आवश्यकता है, और यह स्वचालित रूप से इसे सही थ्रेड पर कॉल करेगा (Action फ़ंक्शन प्रतिनिधि की तरह है)।

आप एक उदाहरण here पा सकते हैं।

बेशक, आपको अन्य कक्षाओं से नियंत्रण प्राप्त करना होगा, उदा। इसे public बनाकर और Window को अपनी अन्य कक्षा में संदर्भित करने के लिए, या शायद केवल प्रगति पट्टी के संदर्भ को पारित करके।

+3

ध्यान दें कि जब आप किसी उदाहरण से लिंक करते हैं, तो प्रासंगिक कोड को प्रतिलिपि/पेस्ट करने के बजाय, यदि वह पृष्ठ कभी भी नीचे चला जाता है (इस सुबह की तरह) या उनकी सामग्री को हटा देता है, तो इस उत्तर में उस पदार्थ के लिए आवश्यक पदार्थ नहीं है काम करने के लिए। उस सामग्री को शामिल करने के लिए बेहतर है। – vapcguy

1

आपको update UI के लिए अपने मुख्य धागे (जिसे UI thread भी कहा जाता है) पर वापस आना होगा। आपके यूआई को अपडेट करने का प्रयास करने वाला कोई अन्य थ्रेड सिर्फ exceptions को पूरे स्थान पर फेंकने का कारण बनता है।

इसलिए क्योंकि आप WPF में हैं, आप Dispatcher और अधिक विशेष रूप से पर beginInvoke का उपयोग कर सकते हैं। यह यूआई थ्रेड में आपको क्या करने की आवश्यकता है (आमतौर पर यूआई अपडेट करें) निष्पादित करने की अनुमति देगा।

तुम भी UI "पंजी" करने के लिए अपने business, एक नियंत्रण/फ़ॉर्म के लिए एक संदर्भ बनाए रखने के द्वारा चाहते migh है, तो आप अपने dispatcher उपयोग कर सकते हैं।

+0

डब्ल्यूपीएफ के लिए नए आने वालों के लिए वाक्यविन्यास का एक उदाहरण सहायक होगा। – vapcguy

4

जो कुछ भी यूआई के साथ इंटरैक्ट करता है उसे UI थ्रेड में कॉल किया जाना चाहिए (जब तक कि यह एक जमे हुए ऑब्जेक्ट न हो)। ऐसा करने के लिए, आप प्रेषक का उपयोग कर सकते हैं।

var disp = /* Get the UI dispatcher, each WPF object has a dispatcher which you can query*/ 
disp.BeginInvoke(DispatcherPriority.Normal, 
     (Action)(() => /*Do your UI Stuff here*/)); 

मैं यहां BeginInvoke का उपयोग करता हूं, आमतौर पर एक पृष्ठभूमि कार्यकर्ता को UI अपडेट का इंतजार करने की आवश्यकता नहीं होती है। यदि आप प्रतीक्षा करना चाहते हैं, तो आप Invoke का उपयोग कर सकते हैं। लेकिन आपको सावधान रहना चाहिए कि BeginInvoke को अक्सर तेज़ी से कॉल न करें, यह वास्तव में बुरा हो सकता है।

वैसे, पृष्ठभूमिवर्कर वर्ग इस तरह के taks के साथ मदद करता है। यह रिपोर्टिंग परिवर्तनों को प्रतिशत की तरह अनुमति देता है और पृष्ठभूमि थ्रेड से स्वचालित रूप से ui थ्रेड में भेजता है। अधिकांश धागे <> अद्यतन ui कार्यों के लिए BackgroundWorker एक शानदार उपकरण है।

1

यदि यह एक लंबी गणना है तो मैं पृष्ठभूमि कार्यकर्ता जाऊंगा। इसमें प्रगति का समर्थन है। इसे रद्द करने के लिए भी समर्थन है।

http://msdn.microsoft.com/en-us/library/cc221403(v=VS.95).aspx 

यहां मेरे पास टेक्स्टबॉक्स सामग्री से जुड़ा हुआ है।

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     Debug.Write("backgroundWorker_RunWorkerCompleted"); 
     if (e.Cancelled) 
     { 
      contents = "Cancelled get contents."; 
      NotifyPropertyChanged("Contents"); 
     } 
     else if (e.Error != null) 
     { 
      contents = "An Error Occured in get contents"; 
      NotifyPropertyChanged("Contents"); 
     } 
     else 
     { 
      contents = (string)e.Result; 
      if (contentTabSelectd) NotifyPropertyChanged("Contents"); 
     } 
    } 
+0

मैं इसे वोट दूंगा, क्योंकि यह मुझे सही रास्ते पर और एक एमएसडीएन पृष्ठ पर मिला जिसकी मुझे आवश्यक जानकारी थी, लेकिन यह एक पूर्ण उदाहरण से एफएआर है। आपको * अधिक * दिखाने की ज़रूरत है, जैसे कार्यकर्ता, संपत्तियों और ईवेंट हैंडलर को इसे तुरंत देने के लिए, यह दिखाएं कि 'DoWork' फ़ंक्शन क्या कर रहा था और इसकी प्रगति की रिपोर्ट कैसे करें। यह केवल दिखाता है कि जब आप कार्यकर्ता को रद्द करते हैं और 'e.Result' दिखाते हैं तो संभवतः आपके पास' BackgroundWorker_DoWork (ऑब्जेक्ट प्रेषक, DoWorkEventArgs e) {...} 'फ़ंक्शन आपको दे रहा है, लेकिन वास्तव में' DoWork' क्या नहीं है कर रहे हैं और इसे 'परिणाम' के रूप में कैसे वापस करें। – vapcguy

5

आप सही है कि आप यूआई धागे पर नियंत्रण को अद्यतन करने के Dispatcher का उपयोग करना चाहिए, और यह भी सही है कि लंबे समय से चल प्रक्रियाओं यूआई थ्रेड पर चलते नहीं करना चाहिए रहे हैं। भले ही आप यूआई थ्रेड पर असीमित रूप से लंबी चलती प्रक्रिया चलाते हैं, फिर भी यह प्रदर्शन समस्याओं का कारण बन सकता है।

यह ध्यान दिया जाना चाहिए कि Dispatcher.CurrentDispatcher वर्तमान धागे के लिए प्रेषक को वापस कर देगा, जरूरी नहीं कि यूआई थ्रेड। मुझे लगता है कि यदि आप के लिए उपलब्ध है तो यूआई थ्रेड के प्रेषक का संदर्भ प्राप्त करने के लिए आप Application.Current.Dispatcher का उपयोग कर सकते हैं, लेकिन यदि आपको नहीं है तो आपको यूआई डिस्पैचर को अपने पृष्ठभूमि थ्रेड में पास करना होगा।

आमतौर पर BackgroundWorker के बजाय थ्रेडिंग ऑपरेशंस के लिए मैं Task Parallel Library का उपयोग करता हूं। मुझे बस इसका उपयोग करना आसान लगता है।

उदाहरण के लिए,

Task.Factory.StartNew(() => 
    SomeObject.RunLongProcess(someDataObject)); 

जहां

void RunLongProcess(SomeViewModel someDataObject) 
{ 
    for (int i = 0; i <= 1000; i++) 
    { 
     Thread.Sleep(10); 

     // Update every 10 executions 
     if (i % 10 == 0) 
     { 
      // Send message to UI thread 
      Application.Current.Dispatcher.BeginInvoke(
       DispatcherPriority.Normal, 
       (Action)(() => someDataObject.ProgressValue = (i/1000))); 
     } 
    } 
} 
28

मैं यहाँ आप एक वक्र गेंद फेंकने के लिए जा रहा हूँ। अगर मैंने इसे एक बार कहा है तो मैंने इसे सौ बार कहा है। या BeginInvoke जैसे मार्शलिंग ऑपरेशंस हमेशा यूआई को वर्कर थ्रेड प्रगति के साथ अपडेट करने के लिए सबसे अच्छे तरीके नहीं हैं।

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

  • यह UI और वर्कर थ्रेड के बीच तंग युग्मन को तोड़ता है जो Invoke लगाता है।
  • यूआई थ्रेड को निर्देशित किया जाता है जब UI नियंत्रण अपडेट हो जाते हैं ... जिस तरह से आप वास्तव में इसके बारे में सोचते हैं, वैसे भी यह होना चाहिए।
  • यूआई संदेश कतार को ओवरराइज़ करने का कोई खतरा नहीं है, यदि BeginInvoke कार्यकर्ता धागे से उपयोग किया गया था तो मामला होगा।
  • कार्यकर्ता थ्रेड को UI थ्रेड से प्रतिक्रिया के लिए प्रतीक्षा करने की आवश्यकता नहीं है क्योंकि Invoke के साथ मामला होगा।
  • आपको यूआई और कार्यकर्ता धागे दोनों पर अधिक थ्रूपुट मिलता है।
  • Invoke और BeginInvoke महंगी परिचालन हैं।

तो आपके calcClass में डेटा संरचना बनाएं जो प्रगति की जानकारी रखेगी।

public class calcClass 
{ 
    private double percentComplete = 0; 

    public double PercentComplete 
    { 
    get 
    { 
     // Do a thread-safe read here. 
     return Interlocked.CompareExchange(ref percentComplete, 0, 0); 
    } 
    } 

    public testMethod(object input) 
    { 
    int count = 1000; 
    for (int i = 0; i < count; i++) 
    { 
     Thread.Sleep(10); 
     double newvalue = ((double)i + 1)/(double)count; 
     Interlocked.Exchange(ref percentComplete, newvalue); 
    } 
    } 
} 

फिर अपने MainWindow वर्ग उपयोग में एक DispatcherTimer समय-समय पर प्रगति के बारे में जानकारी सर्वेक्षण करना। को Tick ईवेंट को बढ़ाने के लिए जो भी अंतराल आपकी स्थिति के लिए सबसे उपयुक्त है, को कॉन्फ़िगर करें।

public partial class MainWindow : Window 
{ 
    public void YourDispatcherTimer_Tick(object sender, EventArgs args) 
    { 
    YourProgressBar.Value = calculation.PercentComplete; 
    } 
} 
+1

हैलो ब्रायन, मुझे लगता है कि आपका जवाब सरल और सुरुचिपूर्ण है। मैं आपकी राय में सोच रहा था, प्रेषक टिक फायरिंग कितनी तेज़ है? आपके अनुभव में, एक स्वीकार्य अद्यतन दर क्या है? धन्यवाद। – DoubleDunk

+2

@DoubleDunk: शायद कहीं 500ms और 2000ms के बीच कहीं। कोई भी तेज़ और उपयोगकर्ता अंतर बताने में सक्षम नहीं होंगे। कोई धीमा और उपयोगकर्ता आश्चर्यचकित होंगे कि प्रगति पट्टी क्यों नहीं बढ़ती है। एक अच्छा संतुलन तय करें जो आपके एप्लिकेशन और उपयोगकर्ताओं के लिए सबसे अच्छा काम करता है। –

+0

@BrianGideon अद्यतन दर इस बात पर निर्भर करेगी कि गणना कब तक की जाएगी। यदि इसे दो बार दो बार अपडेट किया गया है और पूरी गणना में केवल 3 सेकंड लगते हैं, तो प्रगति पट्टी में अभी भी बड़ी कूद होगी। यदि दूसरी तरफ कैल्क्यूशनशन 20 मिनट लेते हैं (क्योंकि उनके पास एक मामले में मेरे लिए है) तो 500 एमएमएस बहुत अधिक बार होता है। अच्छा जवाब हालांकि और आमंत्रित करने का एक अच्छा विकल्प! – phil13131

0

लगा BackgroundWorker को छोड़कर, इस बेहतर जवाब जोड़ने के लिए कुछ भी नहीं के रूप में की जरूरत है मेरी मदद करने के लिए लग रहा था, और जवाब यह है कि के साथ काम अब तक बुरी तरह अधूरा था। दिखाने के लिए एक BackgroundWorker प्रक्रिया के साथ

<Image Name="imgNtwkInd" Source="Images/network_on.jpg" Width="50" /> 

यदि आप नेटवर्क या नहीं से जुड़े हैं: के लिए

using System.ComponentModel; 
using System.Windows; 
using System.Windows.Controls; 

public partial class MainWindow : Window 
{ 
    private BackgroundWorker bw = new BackgroundWorker(); 

    public MainWindow() 
    { 
     InitializeComponent(); 

     // Set up background worker to allow progress reporting and cancellation 
     bw.WorkerReportsProgress = true; 
     bw.WorkerSupportsCancellation = true; 

     // This is your main work process that records progress 
     bw.DoWork += new DoWorkEventHandler(SomeClass.DoWork); 

     // This will update your page based on that progress 
     bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 

     // This starts your background worker and "DoWork()" 
     bw.RunWorkerAsync(); 

     // When this page closes, this will run and cancel your background worker 
     this.Closing += new CancelEventHandler(Page_Unload); 
    } 

    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     BitmapImage bImg = new BitmapImage(); 
     bool connected = false; 
     string response = e.ProgressPercentage.ToString(); // will either be 1 or 0 for true/false -- this is the result recorded in DoWork() 

     if (response == "1") 
      connected = true; 

     // Do something with the result we got 
     if (!connected) 
     { 
      bImg.BeginInit(); 
      bImg.UriSource = new Uri("Images/network_off.jpg", UriKind.Relative); 
      bImg.EndInit(); 
      imgNtwkInd.Source = bImg; 
     } 
     else 
     { 
      bImg.BeginInit(); 
      bImg.UriSource = new Uri("Images/network_on.jpg", UriKind.Relative); 
      bImg.EndInit(); 
      imgNtwkInd.Source = bImg; 
     } 
    } 

    private void Page_Unload(object sender, CancelEventArgs e) 
    { 
     bw.CancelAsync(); // stops the background worker when unloading the page 
    } 
} 


public class SomeClass 
{ 
    public static bool connected = false; 

    public void DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker bw = sender as BackgroundWorker; 

     int i = 0; 
     do 
     { 
      connected = CheckConn(); // do some task and get the result 

      if (bw.CancellationPending == true) 
      { 
       e.Cancel = true; 
       break; 
      } 
      else 
      { 
       Thread.Sleep(1000); 
       // Record your result here 
       if (connected) 
        bw.ReportProgress(1); 
       else 
        bw.ReportProgress(0); 
      } 
     } 
     while (i == 0); 
    } 

    private static bool CheckConn() 
    { 
     bool conn = false; 
     Ping png = new Ping(); 
     string host = "SomeComputerNameHere"; 

     try 
     { 
      PingReply pngReply = png.Send(host); 
      if (pngReply.Status == IPStatus.Success) 
       conn = true; 
     } 
     catch (PingException ex) 
     { 
      // write exception to log 
     } 
     return conn; 
    } 
} 

इस तरह आप MainWindow नामक एक XAML पेज एक छवि इस तरह टैग है तो अद्यतन होता है अधिक जानकारी: https://msdn.microsoft.com/en-us/library/cc221403(v=VS.95).aspx

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