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

时间:2014-09-30 08:20:13

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

我有一个方法,我在Thread.Here内调用方法..

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

现在根据我的要求,我想关闭并重启Thread..For关闭并重新启动我正在尝试此代码..

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

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

请帮我关闭并重启我的情况下的线程。 提前谢谢..

4 个答案:

答案 0 :(得分:3)

我建议您查看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,如果是,则执行新任务。

答案 1 :(得分:3)

你应该尽量避免自己管理线程,让CLR为你做这件事。创建线程是一项昂贵的容易出错的活动,最好不要单独使用。

FCL提供了可用于管理线程的类型。看一下QueueUserWorkItem,它将执行回调中给出的一些代码。这种方法适用于您只想说" Go do something"如果/如果完成,你就不在乎,它没有返回值。如果您想查看返回值,并知道某些内容何时完成,请使用tasks

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

答案 2 :(得分:2)

嗯,尝试一些现代的东西。

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

答案 3 :(得分:2)

您当前正在等待线程完成的方式看起来很好 - 线程在代码耗尽时死亡,而Join确保它已完成。

您无法重新启动线程,但您必须创建一个新线程。

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