如何在c#中正确关闭线程

本文关键字:线程 | 更新日期: 2023-09-27 18:24:59

我有一个在线程内部调用的方法。。

 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(); 

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

在我的情况下,请帮助我关闭并重新启动线程。提前谢谢。。

如何在c#中正确关闭线程

我建议您研究一下Task Parallel Library,它可以对其执行进行细粒度控制,并通过CancellationToken结构支持取消机制:

这里有一个例子:

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),如果是这样,则执行一个新任务。

您应该尽量避免自己管理线程,并让CLR为您做到这一点。创建线程是一项代价高昂、容易出错的活动,最好不要管它。

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

我强烈推荐Jeffrey Richer的CLR。它有一个关于线程和在.Net代码中使用它们的不同方法的优秀部分。

呃,试试现代的东西。

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();
}

当前等待线程完成的方式看起来很好——线程在代码用完时会死亡,Join确保它已经完成。

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

我同意你可能想研究现有新技术的其他答案,它们允许更可读的代码。