2009-10-01 18 views
142

मेरे पास पृष्ठभूमि थ्रेड कार्यान्वयन की पसंद के बारे में एक स्टाइलिस्ट सवाल है, मुझे विंडोज़ फॉर्म ऐप पर उपयोग करना चाहिए। वर्तमान में मेरे पास BackgroundWorker एक ऐसे फॉर्म पर है जिसमें अनंत (while(true)) लूप है। इस लूप में मैं रुचि के कुछ होने तक थ्रेड स्नूज़िंग रखने के लिए WaitHandle.WaitAny का उपयोग करता हूं। इवेंट हैंडल में से एक मैं प्रतीक्षा करता हूं "StopThread" ईवेंट ताकि मैं लूप से बाहर निकल सकूं। इस घटना को संकेत दिया गया है जब मेरे ओवरराइड Form.Dispose() से।पृष्ठभूमिवर्कर बनाम पृष्ठभूमि थ्रेड

मैंने कहीं पढ़ा है कि BackgroundWorker वास्तव में उन परिचालनों के लिए है जो आप यूआई को जोड़ना नहीं चाहते हैं और एक सीमित अंत है - जैसे फाइल डाउनलोड करना, या वस्तुओं के अनुक्रम को प्रोसेस करना। इस मामले में "अंत" अज्ञात है और केवल तभी जब खिड़की बंद हो। इसलिए इस उद्देश्य के लिए BackgroundWorker के बजाय पृष्ठभूमि थ्रेड का उपयोग करना मेरे लिए अधिक उपयुक्त होगा?

उत्तर

72

अपने प्रश्न की मेरी समझ से, आप मानक थ्रेड के रूप में BackgroundWorker का उपयोग कर रहे हैं।

कारण BackgroundWorker उन चीजों के लिए अनुशंसित है जिनके लिए आप यूआई थ्रेड को जोड़ना नहीं चाहते हैं क्योंकि यह विन फॉर्म विकास करते समय कुछ अच्छी घटनाओं को उजागर करता है।

जैसी घटनाएं सिग्नल को सिग्नल करने के लिए सिग्नल करने के लिए, और ProgressChanged ईवेंट थ्रेड प्रगति पर जीयूआई अपडेट करने के लिए।

तो यदि आप नहीं हैं, तो इनका उपयोग करने के लिए, मुझे मानक थ्रेड का उपयोग करने में आपको कोई नुकसान नहीं दिख रहा है, जिसके लिए आपको क्या करना है।

+0

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

+0

मुझे लगता है कि BackgroundWorker.IsBusy वह है जो आप वहां देख रहे हैं। – ParmesanCodice

+1

केवल 'रद्द करेंसिंक्स' का उपयोग करें (और 'रद्द करने के लिए परीक्षण' यदि आपका धागा शॉर्ट अंतराल पर मतदान करेगा, यदि आप इसके बजाय अपवाद अपनाना चाहते हैं, तो 'System.Threading.Thread.Abort()' का उपयोग करें जो अपवाद उठाता है थ्रेड ब्लॉक के भीतर, स्थिति के लिए सही मॉडल चुनें। –

2

तो इसे तोड़ दिया नहीं है - जब तक यह ... है सिर्फ मजाक कर रहा :)

लेकिन गंभीरता से BackgroundWorker शायद बहुत से मिलते-जुलते क्या आपके पास पहले से है इसे ठीक है, तो आप शायद शुरुआत आप से इसके साथ शुरू किया था कुछ समय बचा होगा - लेकिन इस बिंदु पर मुझे जरूरत नहीं दिखती है। जब तक कि कुछ काम नहीं कर रहा है, या आपको लगता है कि आपका वर्तमान कोड समझना मुश्किल है, तो मैं आपके पास जो कुछ भी रखता हूं उसके साथ रहूंगा।

1

एक पृष्ठभूमि कार्यकर्ता एक वर्ग है जो एक अलग थ्रेड में काम करता है, लेकिन यह अतिरिक्त कार्यक्षमता प्रदान करता है जो आपको एक साधारण थ्रेड (जैसे कार्य प्रगति रिपोर्ट हैंडलिंग) के साथ नहीं मिलता है।

यदि आपको पृष्ठभूमि कार्यकर्ता द्वारा दी गई अतिरिक्त सुविधाओं की आवश्यकता नहीं है - और ऐसा लगता है कि आप नहीं करते हैं - तो एक थ्रेड अधिक उपयुक्त होगा।

2

मूल अंतर यह है कि आपने कहा है, BackgroundWorker से जीयूआई घटनाएं उत्पन्न करना। यदि थ्रेड को मुख्य जीयूआई थ्रेड के लिए डिस्प्ले अपडेट करने या ईवेंट जेनरेट करने की आवश्यकता नहीं है, तो यह एक साधारण धागा हो सकता है।

10

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

+1

मुझे लगता है कि यह एक अच्छा मुद्दा है। इसलिए मैं जो संदेश लेता हूं वह पृष्ठभूमि कार्यकर्ता का उपयोग करता है यदि आपको फ़ॉर्म के जीवनकाल के दौरान "अस्थायी रूप से" पृष्ठभूमि थ्रेड की आवश्यकता होती है , हालांकि यदि आपको फॉर्म के पूरे जीवनकाल (जो मिनट, घंटे, दिन ...) हो सकता है तो पृष्ठभूमि पृष्ठभूमि की बजाय थ्रेड का उपयोग करें ताकि थ्रेडपूल –

+0

के उद्देश्य का दुरुपयोग न करें: "। .. जो चिंता का विषय हो सकता है क्योंकि उनमें से केवल एक सीमित संख्या है ", क्या आपका मतलब है कि ओएस पर अन्य ऐप्स उन्हें चाहिए और उसी पूल से साझा कर सकते हैं? –

327

मेरे विचार से कुछ ...

  1. उपयोग BackgroundWorker यदि आप एक ही काम है कि पृष्ठभूमि में चलता है और यूआई के साथ बातचीत करने की जरूरत है। मार्शलिंग डेटा और विधि यूआई थ्रेड को विधि कॉल का कार्य अपने ईवेंट-आधारित मॉडल के माध्यम से स्वचालित रूप से संभाला जाता है। BackgroundWorker से बचें अगर ...
    • अपने विधानसभा नहीं है या यूआई के साथ सीधे बातचीत नहीं करता,
    • आप धागा जरूरत है एक अग्रभूमि धागा हो सकता है, या
    • आप धागा प्राथमिकता में हेरफेर करने की जरूरत है।
  2. दक्षता की वांछित होने पर ThreadPool धागे का उपयोग करें। थ्रेडपूल थ्रेड बनाने, शुरू करने और रोकने के साथ जुड़े ओवरहेड से बचने में मदद करता है। ThreadPool अगर प्रयोग करने से बचें ...
    • कार्य अपने आवेदन के जीवन भर के लिए चलाता है,
    • आप धागा जरूरत है एक अग्रभूमि धागा हो सकता है,
    • आप धागा प्राथमिकता में हेरफेर करने की जरूरत है, या
    • आपको थ्रेड की एक निश्चित पहचान (निरस्त करने, निलंबित करने, खोज करने) की आवश्यकता है।
  3. लंबे समय से चल रहे कार्यों के लिए Thread वर्ग का उपयोग करें और जब आप एक औपचारिक सूत्रण मॉडल, जैसे द्वारा की पेशकश की सुविधाओं, अग्रभूमि और पृष्ठभूमि धागे के बीच, सुक्ष्म धागा निष्पादन पर नियंत्रण चयन करते समय, धागा प्राथमिकता सुधार करने से, आदि की आवश्यकता होती है ।
+9

पृष्ठभूमि कार्यकर्ता System.dll गधे में है एम्बली और सिस्टम। कॉम्पोनेंट मॉडल नामस्थान। Winforms पर कोई निर्भरता नहीं है। – Kugel

+14

यह सही है, लेकिन 'पृष्ठभूमिवर्कर' को एक इच्छुक पार्टी को थ्रेड प्रगति की रिपोर्ट करने के लिए डिज़ाइन किया गया है, जिसमें आम तौर पर यूआई शामिल होता है। कक्षा के लिए एमएसडीएन दस्तावेज इस बहुतायत से स्पष्ट बनाता है। यदि आपको पृष्ठभूमि में प्रदर्शन करने के लिए बस एक कार्य की आवश्यकता है, तो 'थ्रेडपूल' थ्रेड का उपयोग करना पसंद करें। –

+5

'System.Windows.Forms' असेंबली के बारे में आपके बिंदु के संबंध में; 'BackgroundWorker' भी WPF ऐप्स के लिए भी उपयोगी है और उन ऐप्स में WinForms का संदर्भ नहीं हो सकता है। – GiddyUpHorsey

11

सुंदर ज्यादा क्या मैट डेविस निम्नलिखित अतिरिक्त अंकों के साथ, ने कहा:

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

ThreadPool के माध्यम से निष्पादित कार्य आसानी से रद्द नहीं किए जा सकते हैं (इसमें ThreadPool शामिल हैं। QueueUserWorkItem और प्रतिनिधि असीमित रूप से निष्पादित होते हैं)। इसलिए जब आपको रद्दीकरण की आवश्यकता होती है, तो आपको रद्दीकरण की आवश्यकता होती है या तो BackgroundWorker या (यूआई के बाहर अधिक संभावना) का उपयोग थ्रेड को स्पिन करें और इसका संदर्भ रखें ताकि आप Abort() पर कॉल कर सकें।

+1

केवल ... उम्मीद है कि एप्लिकेशन को थ्रेडेड कार्य को रोकने के * स्वच्छ * विधि के बारे में डिज़ाइन किया गया है (आमतौर पर यह नहीं है) –

4

मुझे पता था कि .NET को जाने से पहले धागे का उपयोग कैसे करें, इसलिए जब मैंने पृष्ठभूमिवर्कर्स का उपयोग करना शुरू किया, तो कुछ लोगों ने इसका उपयोग किया। मैट डेविस ने उत्कृष्ट उत्कृष्टता के साथ अंतर को सारांशित किया है, लेकिन मैं यह जोड़ूंगा कि यह समझना मुश्किल है कि कोड क्या कर रहा है, और यह डिबगिंग को कठिन बना सकता है। धागे के पूल में काम देने के बारे में सोचने के बजाय थ्रेड, आईएमओ बनाने और बंद करने के बारे में सोचना आसान है।

मैं अभी भी अन्य लोगों की पोस्ट टिप्पणी नहीं कर सकता, इसलिए piers7 संबोधित करने के लिए एक जवाब का उपयोग करने में मेरी क्षणिक लंगड़ापन माफ

Thread.Abort() उपयोग न करें; इसके बजाए, एक घटना को सिग्नल करें और सिग्नल होने पर अपने थ्रेड को गहराई से समाप्त करने के लिए डिज़ाइन करें। Thread.Abort() थ्रेड के निष्पादन में एक मनमानी बिंदु पर एक थ्रेडएबॉर्ट अपवाद उठाता है, जो अनाथ मॉनीटर, भ्रष्ट साझा राज्य, आदि जैसे सभी प्रकार की दुखी चीजें कर सकता है। http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx

8

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

BackgroundWorker का उपयोग करने से पहले सबसे पहले विचार करें कि क्या आप थ्रेड (बंद करने वाला ऐप, उपयोगकर्ता रद्दीकरण) रद्द करना चाहते हैं तो आपको यह तय करने की आवश्यकता है कि क्या आपके थ्रेड को रद्दीकरण की जांच करनी चाहिए या यदि इसे निष्पादन पर ही जोर दिया जाना चाहिए।

BackgroundWorker.CancelAsync()true को CancellationPending सेट हो जाएगा, लेकिन कुछ भी अधिक काम नहीं चलेगा, यह तो धागे जिम्मेदारी है लगातार इस जांच करने के लिए, कि आप इस दृष्टिकोण में एक रेस स्थिति है जहाँ आपके उपयोगकर्ता को रद्द कर दिया लग सकती है को ध्यान में रखना भी है, लेकिन धागा CancellationPending के परीक्षण से पहले पूरा हुआ।

Thread.Abort() दूसरी तरफ थ्रेड निष्पादन के भीतर एक अपवाद फेंक देगा जो उस धागे को रद्द करने के लिए लागू करता है, आपको इस बारे में सावधान रहना चाहिए कि क्या यह अपवाद अचानक निष्पादन में उठाया गया था।

थ्रेडिंग कोई फर्क नहीं पड़ता बहुत सावधानी से विचार करने की जरूरत है क्या काम, कुछ आगे पढ़ने के लिए:

Parallel Programming in the .NET Framework Managed Threading Best Practices

0

मैं BackgroundWorker वर्ग कि अभी तक का उल्लेख नहीं किया गया था में से एक व्यवहार का कहना चाहते हैं। थ्रेड.इस्बैकग्राउंड प्रॉपर्टी सेट करके आप पृष्ठभूमि में चलाने के लिए सामान्य थ्रेड बना सकते हैं।

पृष्ठभूमि धागे अग्रभूमि धागे के समान हैं, सिवाय इसके कि पृष्ठभूमि धागे प्रक्रिया को समाप्त होने से नहीं रोकते हैं। [1]

आप अपनी प्रपत्र विंडो के निर्माता में निम्न विधि को कॉल करके इस व्यवहार का परीक्षण कर सकते हैं।

void TestBackgroundThread() 
{ 
    var thread = new Thread((ThreadStart)delegate() 
    { 
     long count = 0; 
     while (true) 
     { 
      count++; 
      Debug.WriteLine("Thread loop count: " + count); 
     } 
    }); 

    // Choose one option: 
    thread.IsBackground = false; // <--- This will make the thread run in background 
    thread.IsBackground = true; // <--- This will delay program termination 

    thread.Start(); 
} 

जब IsBackground संपत्ति सत्य पर सेट की जाती है और आप विंडो बंद करते हैं, तो आपका एप्लिकेशन मानक को समाप्त कर देगा।

लेकिन जब IsBackground प्रॉपर्टी को गलत पर सेट किया गया है (डिफ़ॉल्ट रूप से) और आप विंडो बंद कर देते हैं, तो बस विंडो अपमानित होगी लेकिन प्रक्रिया अभी भी चलती रहेगी।

पृष्ठभूमिवर्कर वर्ग पृष्ठभूमि में चलने वाले थ्रेड का उपयोग करता है।

0

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

यह आपको अपनी सेवा पर साफ खींचें और ड्रॉप नियंत्रण देता है लेकिन ... इसे तैनात करने की भी कोशिश न करें। काम नहीं करेगा

सेवाएं: तभी इसका उपयोग System.Timers.Timer System.Windows.Forms.Timer भले ही यह पिटारे में उपलब्ध है

सेवाएं काम नहीं करेगा: जब यह एक सेवा के रूप में चल रहा है BackgroundWorkers काम नहीं करेगा सिस्टम का उपयोग करें। थ्रेडिंग। इसके बजाय थ्रेडपूल या असिनक

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