2012-05-06 28 views
12

मैं थ्रेड को रोक/फिर से कैसे शुरू कर सकता हूं? एक बार जब मैं Join() धागा करता हूं, तो मैं इसे पुनरारंभ नहीं कर सकता। तो मैं थ्रेड कैसे शुरू कर सकता हूं और बटन को 'रोक' दबाए जाने पर इसे रोक सकता हूं, और फिर से शुरू होने पर बटन फिर से शुरू कर सकता है?थ्रेड को रोकने/फिर से शुरू करने के लिए

यह धागा केवल एक चीज करता है, लेबल नियंत्रण में कुछ यादृच्छिक पाठ दिखाता है।

+1

क्या आप अपने प्रश्न में अपना कोड जोड़ सकते हैं – Adil

+0

इस समय कोई कोड नहीं है। मैं अभी भी सोच रहा हूं कि इस परियोजना को मेरे सिर में कैसे कार्यान्वित किया जाए। एक बार धागा मुख्य थ्रेड के साथ जुड़ने के बाद, मैं आपको बता सकता हूं कि थ्रेडिंग के साथ अपने काम के अनुभव से मुझे पता है, मैं इसे फिर से शुरू/पुनरारंभ नहीं कर सकता हूं। – Yustme

उत्तर

16

शायद ManualResetEvent एक अच्छा विकल्प है। एक छोटी उदाहरण:

private static EventWaitHandle waitHandle = new ManualResetEvent(initialState: true); 

// Main thread 
public void OnPauseClick(...) { 
    waitHandle.Reset(); 
} 

public void OnResumeClick(...) { 
    waitHandle.Set(); 
} 

// Worker thread 
public void DoSth() { 
    while (true) { 
    // show some random text in a label control (btw. you have to 
    // dispatch the action onto the main thread) 
    waitHandle.WaitOne(); // waits for the signal to be set 
    } 
} 
+0

वर्चुअलबॉक्स एक्सपी में काम नहीं करते हैं। पता नहीं क्यों? – zionpi

+0

मैं एक परिवर्तनीय नाम के रूप में एक [_reserved कीवर्ड_] (https://msdn.microsoft.com/en-us/library/x53a06bb.aspx) का उपयोग करने के लिए डाउनवोट करने का लुत्फ उठा रहा था, लेकिन समाधान मेरे लिए ट्रोल करने के लिए पूरी तरह से बहुत अच्छा काम करता था :-) – MDMoore313

+0

मैं घटनाओं को परिभाषित नहीं कर रहा हूं (♡ आरएक्स ♡), इसलिए मुझे पता नहीं था कि 'event' एक कीवर्ड है :-) –

5

मेरा सुझाव है कि आप Threading in C#, by Joe Albahari, पढ़ने के लिए विशेष रूप से Suspend and Resume अनुभाग:

एक धागा स्पष्ट रूप से निलंबित किया जा सकता है और पदावनत तरीकों Thread.Suspend और Thread.Resume के माध्यम से शुरू हुआ। यह तंत्र अवरुद्ध करने के लिए पूरी तरह से अलग है। दोनों प्रणालियां स्वतंत्र हैं और समानांतर में संचालित होती हैं।

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

.NET 2.0, को निलंबित और फिर से शुरू करें अमान्य हो जाने, उनके उपयोग खतरे मनमाने ढंग से एक और धागा निलंबित में निहित की वजह से हतोत्साहित से

। यदि किसी महत्वपूर्ण संसाधन पर लॉक रखने वाला धागा निलंबित कर दिया गया है, तो संपूर्ण एप्लिकेशन (या कंप्यूटर) डेडलॉक कर सकता है। यह एबॉर्ट को कॉल करने से कहीं अधिक खतरनाक है - जिसके परिणामस्वरूप अंततः ब्लॉक में कोड के आधार पर ऐसे किसी भी ताले को जारी किया जा सकता है (कम से कम सैद्धांतिक रूप से)।

SuspendRequested state

+0

आपका ब्लॉक उद्धरण अवरुद्ध थ्रेड के विरुद्ध एक निलंबित धागे के बीच एक अंतर बनाता है, लेकिन चित्र इस भेद को प्रतीत नहीं करता है। क्या यह जानबूझकर है? – Tung

+0

@gliderkite, कोड दिखाने के बारे में आदिल को मेरी प्रतिक्रिया देखें। – Yustme

+0

@ टंग ए थ्रेड को अवरुद्ध माना जाता है जब उसके निष्पादन को किसी कारण से रोक दिया जाता है, जैसे कि जब सोना या किसी अन्य के लिए जॉइन या एंडइनवोक के माध्यम से समाप्त होना। कोड में: 'बूल अवरुद्ध = (कुछ थ्रेड। थ्रेडस्टेट और थ्रेडस्टेट। वैट स्लीप जोइन)! = 0; '। तो आरेख में कोई भेद क्यों नहीं है। [यह] देखें (http://www.albahari.com/threading/part2.aspx#_Blocking)। – gliderkite

2

यह सबसे अच्छा विचार मैन्युअल निलंबित नहीं कर रहा है करने के लिए और धागे को फिर से शुरू। हालांकि, आप आसानी से थ्रेड सिंक्रनाइज़ेशन प्राइमेटिव्स (ManualResetEvent)

this question पर एक नज़र डालें, तो आप इसे उपयोगी पा सकते हैं।

लेकिन मेरा मानना ​​है कि आप समय-समय पर टाइमर का उपयोग कर 'लेबल नियंत्रण में यादृच्छिक पाठ दिखाने' के अपने लक्ष्य को आसानी से प्राप्त कर सकते हैं।

यहाँ आप फिर से timer.Stop() को फोन करके यह रोक सकते हैं और उसके बाद फिर से शुरू करने timer.Start()DispatcherTimer

var timer = new DispatcherTimer(); 
timer.Tick += (s, e) => Label.Text = GetRandomText(); 
timer.Interval = TimeSpan.FromMilliseconds(500); 
timer.Start(); 

का उपयोग कर एक त्वरित उदाहरण है।

+0

हाय, यह अच्छा लगता है, क्या मैं इस कोड को एक अलग थ्रेड में भी डाल सकता हूं ? क्योंकि मैं जीयूआई थ्रेड को अवरुद्ध नहीं करना चाहता हूं। – Yustme

+0

@Yustme: AFAIK GUI थ्रेड पर 'DispatcherTimer' निष्पादित करता है। यदि आप एक अलग धागा 'System.Threading.Timer' का उपयोग करना चाहते हैं। – Tudor

+0

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

1

यहां दो तरीके हैं जो मेरे लिए काम करते हैं। दोनों मानते हैं कि कार्यकर्ता धागे का अपना प्रसंस्करण पाश है।

  1. का उपयोग कर, धागा एक कॉलबैक आह्वान जा रहा
  2. माता पिता संकेत करने के लिए यह

सांत्वना आवेदन उदाहरण नीचे दोनों दृष्टिकोण से पता चलता धागा के वर्ग पर एक विधि आह्वान है रखने के लिए अनुमति का अनुरोध करना है रोकने/जारी रखने के लिए एक कॉलबैक, और रोकने के लिए एक कार्यकर्ता विधि।कॉलबैक विधि का एक अन्य लाभ यह है कि जारी रखने की अनुमति की जांच करते समय बैक स्टेटस अपडेट पास करना भी सुविधाजनक है।

using System; 
using System.Threading; 

namespace ConsoleApplication7 
{ 
    class Program 
    { 
     static bool keepGoing; 
     static void Main(string[] args) 
     { 
      keepGoing = true; 
      Worker worker = new Worker(new KeepGoingDelegate(KeepGoing)); 
      Thread thread = new Thread(worker.DoWork); 
      thread.IsBackground = true; 
      thread.Start(); 

      while (thread.ThreadState != ThreadState.Stopped) 
      { 
       switch (Console.ReadKey(true).KeyChar) 
       { 
        case 'p': 
         keepGoing = false; 
         break; 
        case 'w': 
         keepGoing = true; 
         break; 
        case 's': 
         worker.Stop(); 
         break; 
       } 
       Thread.Sleep(100); 
      } 
      Console.WriteLine("Done"); 
      Console.ReadKey(); 
     } 

     static bool KeepGoing() 
     { 
      return keepGoing; 
     } 
    } 

    public delegate bool KeepGoingDelegate(); 
    public class Worker 
    { 
     bool stop = false; 
     KeepGoingDelegate KeepGoingCallback; 
     public Worker(KeepGoingDelegate callbackArg) 
     { 
      KeepGoingCallback = callbackArg; 
     } 

     public void DoWork() 
     { 
      while (!stop) 
      { 
       Console.Write(KeepGoingCallback()?"\rWorking":"\rPaused "); 

       Thread.Sleep(100); 
      } 
      Console.WriteLine("\nStopped"); 
     } 

     public void Stop() 
     { 
      stop = true; 
     } 
    } 
} 
+0

हाय, मेरे जीवन के लिए मुझे प्रतिनिधियों को समझने में परेशानी हो रही है। मैं थ्रेड को रोकने के तरीके को समझ सकता हूं, लेकिन मुझे समझ में नहीं आता कि आप इसे कैसे पुनरारंभ कर रहे हैं? – Zev

+0

@Zev - एक विधि के लिए एक प्रतिनिधि समायोजक प्लेसहोल्डर, ताकि आप इसे किसी अन्य वर्ग के उदाहरण में पारित कर सकें ताकि वह इसे निष्पादित कर सके। मेरे उदाहरण में माता-पिता 'KeepGoing()' विधि को कार्यकर्ता में पास करता है, जो समय-समय पर माता-पिता के साथ जांच करने के लिए कहता है कि यह जारी रखना चाहिए या नहीं। कार्यकर्ता थ्रेड प्रत्येक बार पुनरारंभ नहीं करता है - यह एक बार लॉन्च होता है और जब तक यह स्टॉप सिग्नल न हो जाए तब तक चलता रहता है। –

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