2013-02-14 12 views
10

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

पकड़ है कि उपयोगकर्ता जीयूआई के दूसरे हिस्से में ले जाने से पहले हो सकता है काम खत्म हो गया है, और उस मामले में, मैं करने के लिए है:

  1. रद्द चल रहे कार्य (अगर यह सक्रिय है)
  2. इसे रद्द करने तक प्रतीक्षा करें: यह महत्वपूर्ण है, क्योंकि समय लेने वाले कार्य का उद्देश्य एक विशिष्ट नियंत्रण को अद्यतन करना है। यदि एक से अधिक धागे इसे एक साथ करने की कोशिश करते हैं, तो चीजें गन्दा हो सकती हैं।
  3. लॉन्च खरोंच

से काम के लिए एक ठोस उदाहरण के लिए, कल्पना प्रपत्र के दो भाग हैं: एक है जहाँ आप एक निर्देशिका वृक्ष जाएँ, और एक और जहाँ आप थंबनेल प्रदर्शित करते हैं। जब उपयोगकर्ता किसी अन्य निर्देशिका में नेविगेट करता है, तो थंबनेल को रीफ्रेश करने की आवश्यकता होती है।

सबसे पहले मैंने रद्दीकरण की प्रतीक्षा करने के लिए BackgroundWorker और AutoResetEvent का उपयोग करने के बारे में सोचा, लेकिन मुझे कुछ गड़बड़ करनी चाहिए क्योंकि रद्द करने के दौरान मुझे समय-समय पर खारिज कर दिया गया था। तब मैंने टीपीएल के बारे में पढ़ा, जिसे बीजीडब्ल्यू और अधिक आदिम तंत्र को प्रतिस्थापित करना है।

क्या यह आसानी से टीपीएल का उपयोग करके किया जा सकता है?

उत्तर

18

कुछ बातें ध्यान रखें:

  • आप एक CancellationTokenSource

  • टास्क रद्दीकरण से एक CancellationToken प्राप्त कर सकते हैं एक सहकारी कार्रवाई है: अगर अपने कार्य को समय-समय पर CancellationToken.IsCancellationRequested संपत्ति की जांच नहीं करता, इससे कोई फ़र्क नहीं पड़ता कि आप कार्य को रद्द करने का कितनी बार प्रयास करते हैं, यह आसानी से दूर हो जाएगा।

उन चीजों कहा, यहां एक सामान्य उपाय है:

void Main() 
{ 
    var tokenSource = new CancellationTokenSource(); 
    var myTask = Task.Factory 
     .StartNew(() => DoWork(tokenSource.Token), tokenSource.Token); 

    Thread.Sleep(1000); 

    // ok, let's cancel it (well, let's "request it be cancelled") 
    tokenSource.Cancel(); 

    // wait for the task to "finish" 
    myTask.Wait(); 
} 

public void DoWork(CancellationToken token) 
{ 
    while(!token.IsCancellationRequested) 
    { 
     // Do useful stuff here 
     Console.WriteLine("Working!"); 
     Thread.Sleep(100); 
    } 
} 
+0

यह सिर्फ एक बार हर बार टोकन स्रोत बना सकते हैं और 'StartNew' करने के लिए अपने टोकन पारित करने के लिए ठीक है? –

+0

इसे एक स्ट्रिंग पर एक बच्चे के दो डिब्बे की तरह सोचें (ठीक है, एक से एन डिब्बे: आपके पास एक अंत है और सभी प्रारंभिक कार्य गेटा कर सकते हैं। आप एक छोर में "रद्द करें" चिल्लाते हैं, टोकन साझा करने वाले सभी इसे सुनेंगे – JerKimball

+1

@dario_ramos मेरा मानना ​​है कि आपकी टिप्पणी में दिए गए प्रश्न का उत्तर एक टिप्पणी में दिया गया था [यहां] (http://stackoverflow.com/questions/14896248/deadlock-when-waiting-for-task-to-finish), लेकिन पूर्णता के लिए 'खासतौर से, जवाब नहीं है -' रद्दीकरण टोकन स्रोत 'को रीसेट नहीं किया जा सकता है और फिर से रद्द नहीं किया जा सकता है; यदि आप एक पर रद्दीकरण का अनुरोध करते हैं तो आपको इसे फिर से रद्द करना चाहते हैं, तो आपको इसे एक नए से बदलना होगा। – shambulator

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