3

Given 是一个非常常见的线程场景:

宣言

private Thread _thread;
private bool _isRunning = false;

开始

_thread = new Thread(() => NeverEndingProc());
thread.Start();

方法

private void NeverEndingProc() {
    while(_isRunning) {
        do();
    }
}

可能用于异步 tcp 侦听器,该侦听器等待回调,直到它通过让线程用完而停止(_isRunning = false)。

现在我想知道:是否可以用 做同样的事情Task?使用CancellationToken? 还是Tasks 仅适用于预期结束并报告状态的程序?

4

2 回答 2

3

您当然可以通过传递NeverEndingProc到 来做到这一点Task.Run

然而,在功能上有一个重要的区别:如果一个异常从NeverEndingProc一个 bare传播出去Thread,它将使进程崩溃。如果它在 aTask中,它将引发TaskScheduler.UnobservedException然后被默默地忽略(从 .NET 4.5 开始)。

也就是说,您可以探索其他选择。例如,响应式扩展几乎消除了对“无限线程循环”的任何需求。

于 2013-11-12T13:43:42.310 回答
1

使用 Task + CancellationToken 的原因之一是使各个进程及其取消彼此更加独立。在您的示例中,请注意如何NeverEndingProc需要直接引用_isRunning同一类中的字段。相反,您可以接受外部令牌:

开始:

public void StartNeverEndingProc(CancellationToken token) {
    Task.Factory.StartNew(() => NeverEndingProc(token), token);
}

方法:

private void NeverEndingProc(CancellationToken token) {
    while (true) {
        token.ThrowIfCancellationRequested();
        do();
    }
}

现在取消由调用者管理,并且可以应用于多个独立任务:

var instance = new YourClass();

var cts = new CancellationTokenSource();

instance.StartNeverEndingProc(cts.Token);  // start your task
StartOtherProc(cts.Token);  // start another task

cts.Cancel();  // cancel both
于 2013-11-12T14:53:27.833 回答