2011-08-04 8 views
5

मेरे डब्ल्यूपीएफ एप्लिकेशन में, मुझे समानांतर में 2 लंबे समय तक चलने वाले कार्यों को चलाने की आवश्यकता है, जो यूआई में दिखाए जाने वाले डेटा को वापस लौटाते हैं।सी # .NET कार्य: एकाधिक कार्यों को पूरा होने पर अधिसूचना कैसे प्राप्त करें

मेरे पास IsBusy नामक मेरे दृश्य मॉडल में एक संपत्ति है, जो दोनों कार्य पूरा होने तक सत्य होना चाहिए।

2 लंबे समय तक चलने वाले कार्यों को पूरा करने पर मुझे अधिसूचना कैसे प्राप्त करें?

मैं टास्क.WaitAll का उपयोग नहीं करना चाहता, क्योंकि यह मेरे यूआई थ्रेड को अवरुद्ध करेगा। मैं ContinueWith का उपयोग करके कार्यों को श्रृंखलाबद्ध नहीं करना चाहता, क्योंकि मैं उन लंबे समय तक चलने वाले कार्यों को समानांतर में चलाने के लिए चाहता हूं।

उत्तर

4

टास्कशेड्यूलर का उपयोग करें। फ्रॉम कंटेंट सिंक्रनाइज़ेशन कॉन्टेक्स्ट() और इसे टास्कफ़ैक्टरी में पास करें। कंटिन्यूहेनएल (...) दोनों कार्यों को पूरा करने के बाद यूआई अपडेट करने के लिए।

+0

यह वही है जो मैं ढूंढ रहा हूं। मुझे संदेह था कि ढांचे में ऐसा कुछ था, मुझे बस यह नहीं मिला। – Mas

0

मुझे लगता है कि आपका उत्तर कॉलबैक है।

अपने लंबे समय से चलने वाले धागे को सेट करते समय, किसी विधि के संदर्भ में पास करें। आप या तो कॉलबैक विधि को कार्य विधि में पास कर सकते हैं, या आप एक AsyncCallback प्रतिनिधि उदाहरण स्थापित कर सकते हैं, जो प्रतिनिधियों की BeginInvoke() सुविधा में बनाया गया है।

यहाँ एक बुनियादी उदाहरण है:

public void StartMyTwoTasks() 
{ 
    //I'm passing the callback to the task method directly; you may prefer to pass it to BeginInvoke() 
    var task1Lambda =()=>Task1(TaskCompleted); 
    var task2Lambda =()=>Task2(TaskCompleted); 

    task1Lambda.BeginInvoke(null,null); 
    task2Lambda.BeginInvoke(null,null); 
} 

public void Task1(Action<int> task1Complete) 
{ 
    //perform your long-running calculation or data retrieval/transformation here 
    Thread.Sleep(10000); 
    //when finished, call the callback method. 
    //You may need to use Control.Invoke() to make sure the callback is executed on the UI thread 
    //If you use the AsyncCallback feature of BeginInvoke/EndInvoke, you don't have to make the call here. 
    taskComplete(1); 
} 

public void Task2(Action<int> taskComplete) 
{ 
    //Ditto 
    Thread.Sleep(8000); 

    taskComplete(2); 
} 

public void Task1Complete(int taskNumber) 
{ 
    TasksComplete[taskNumber-1] = true; 
    If(TasksComplete.All(x=>x==true)) 
     DoSomethingOnceAllTasksAreComplete(); 
} 

AsyncCallback सुविधा का उपयोग, अपने कॉलबैक विधि एक विशेष प्रतिनिधि परिभाषा यह है कि IAsyncResult स्वीकार करता है के अनुरूप है, लेकिन आप में ठीक से लागू बारे में चिंता करने की जरूरत नहीं है आपकी विधि; ढांचा आपके लिए कॉलबैक को संभालता है:

public public void StartALongTask() 
{ 
    var taskLambda =()=>PerformTask(); 

    taskLambda.BeginInvoke(TaskComplete,null); 
} 

//one advantage is that you can call a method that returns a value very easily. 
public IEnumerable<string> PerformTask() 
{ 
    //long-running task 
    Thread.Sleep(5000); 

    return Enumerable.Repeat("result", 100); 

    //look ma, no callback invocation. 
    //This makes asynchronous delegates very useful for refactoring a synchronous 
    //operation without a lot of code changes. 
} 

//Here's the callback, which is invoked properly by the runtime when the thread is complete 
public void TaskComplete(IASyncResult ar) 
{ 
    //calling EndInvoke on the same delegate, which is available in the AsyncResult, 
    //returns the return value of that delegate as if you'd called it synchronously. 
    var results = ar.AsyncDelegate.EndInvoke(ar); 

    //Now you can do something with those results. 
} 

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

0

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

4

एक तरीका बनाना होगा तीसरे धागे जो उन कार्यों को जन्म देते हैं, और दो कार्य पूरा होने तक थ्रेड निकास में देरी के लिए Task.WaitAll का उपयोग करता है। उस धागे के अंत में आप किसी ईवेंट को आग लगा सकते हैं या कॉलबैक फ़ंक्शन निष्पादित कर सकते हैं।

आप BackgroundWorker का उपयोग कर इसे और भी आसान बना सकते हैं, जिसमें RunWorkerCompleted नामक एक अंतर्निहित ईवेंट है। यह आपको थ्रेड पूल पर रखेगा ताकि आपको उस धागे के प्रबंधन के साथ चिंतित होने की आवश्यकता न हो।

3

Task.Factory.ContinueWhenAll आज़माएं। यह Tasks की एक सरणी लेता है और जब वे पूरी तरह से होते हैं तो असीमित रूप से ऑपरेशन बंद हो जाता है।

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