【问题标题】:How to close a Thread properly in c#如何在c#中正确关闭线程
【发布时间】:2014-09-30 08:20:13
【问题描述】:

我有一个在 Thread 中调用的方法。这里是方法..

 private System.Threading.Thread _thread;
 private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);

 private void DoWork()
    {
        while (!_shutdownEvent.WaitOne(0))
        { 
              //Business logic
        }
    }

现在我在这里开始线程..

 _thread = new Thread(DoWork);
 _thread.Start();

现在根据我的要求,我想关闭并重新启动线程。为了关闭和重新启动,我正在尝试这段代码。

  _shutdownEvent.Set();  // trigger the thread to stop
  _thread.Join(); 

但我认为这不是关闭线程并重新启动它的正确方法..

请帮助我关闭并重新启动线程。 提前谢谢..

【问题讨论】:

  • 您使用的是哪个 .NET 框架版本?
  • @YuvalItzchakov .Net4.0
  • @shubhamHegdey 在这种情况下您可以考虑使用 TPL
  • 还有其他方法,但我真的不认为你的做法有问题。
  • 您是否要取消正在进行的工作并重新启动它?这里发生的唯一iffy 是低级线程代码,但它在功能上似乎是合理的。

标签: c# .net multithreading task-parallel-library


【解决方案1】:

我建议您查看Task Parallel Library,它可以通过CancellationToken 结构对其执行和supports a cancellation mechanism 进行细粒度控制:

这是一个例子:

var tokenSource = new CancellationTokenSource();
CancellationToken ct = tokenSource.Token;

var task = Task.Factory.StartNew(() =>
{
        // Were we already canceled?
        ct.ThrowIfCancellationRequested();

        bool moreToDo = true;
        while (moreToDo)
        {
            // Poll on this property if you have to do 
            // other cleanup before throwing. 
            if (ct.IsCancellationRequested)
            {
                // Clean up here, then...
                ct.ThrowIfCancellationRequested();
            }

        }
    }, tokenSource.Token); // Pass same token to StartNew.

tokenSource.Cancel();

关于“重启线程”,你不能重启给定的Task。你可以做的是看到它被取消了(一个任务包含一个Status属性,一旦你取消它就会变成Canceled),如果是这样,执行一个新任务。

【讨论】:

    【解决方案2】:

    您确实应该尽量避免自己管理线程,而让 CLR 为您做这件事。创建线程是一项代价高昂且容易出错的活动,最好别管它。

    FCL 提供了可用于管理线程的类型。看看QueueUserWorkItem,它将执行回调中给出的一些代码。这在您只想说“去做某事”并且您不在乎何时/是否完成并且没有返回值的情况下效果很好。如果您想查看返回值并知道某事何时完成,请使用tasks。

    我强烈推荐 Jeffrey Richer 的 CLR via C#。它有一个关于线程以及在 .Net 代码中使用它们的不同方式的精彩部分。

    【讨论】:

      【解决方案3】:

      呃,试试现代的吧。

      private Task DoWork(CancellationToken token)
      {
          while (!token.IsCancellationRequested)
          {
              // ... It would be nice if you could await something here.
          }
      
          return Task.FromResult(true);
      }
      

      然后,只需发送信号 CancellationToken,

      using (var cts = new CancellationTokenSource())
      {
          await Task.WhenAny(
              DoWork(cts.Token),
              SomeOtherWork())
      
          cts.Cancel();
      }
      

      【讨论】:

        【解决方案4】:

        您当前等待线程完成的方式看起来不错 - 线程在代码用完时死亡,Join 确保它已经完成。

        你不能重新启动一个线程,你必须创建一个新的。

        我同意您可能希望研究可用新技术的其他答案,它们允许更可读的代码。

        【讨论】:

          猜你喜欢
          • 2014-06-11
          • 2014-11-24
          • 1970-01-01
          • 1970-01-01
          • 2020-04-01
          • 1970-01-01
          • 2018-04-30
          • 1970-01-01
          • 2011-04-26
          相关资源
          最近更新 更多