C# 使用任务的经典永无止境线程循环?
给出了一个非常常见的线程场景: 声明C# 使用任务的经典永无止境线程循环?,c#,multithreading,asynchronous,task-parallel-library,C#,Multithreading,Asynchronous,Task Parallel Library,给出了一个非常常见的线程场景: 声明 private Thread _thread; private bool _isRunning = false; 开始 方法 private void NeverEndingProc() { while(_isRunning) { do(); } } 可能在异步tcp侦听器中使用,该侦听器等待回调,直到通过让线程耗尽而停止(\u isRunning=false) 现在我想知道:有没有可能对任务做同样的事情?使用取消令牌?或
private Thread _thread;
private bool _isRunning = false;
开始
方法
private void NeverEndingProc() {
while(_isRunning) {
do();
}
}
可能在异步tcp侦听器中使用,该侦听器等待回调,直到通过让线程耗尽而停止(\u isRunning=false
)
现在我想知道:有没有可能对任务做同样的事情?使用取消令牌
?或者,Task
s仅适用于预期结束并报告状态的过程?您当然可以通过将NeverEndingProc
传递给Task.Run
来完成此操作
但是,在功能上有一个重要的区别:如果异常从裸线程中的NeverEndingProc
传播出去,它将使进程崩溃。如果它位于任务中
,它将引发任务调度程序。未观察到的异常
,然后被静默忽略(从.NET 4.5开始)
也就是说,你可以探索其他选择,例如,几乎不需要“无限线程循环”。使用Task+CancellationToken的一个原因是使各个进程及其取消更加独立。在您的示例中,请注意NeverEndingProc
如何需要直接引用同一类中的\u 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
您只想使用tasks创建一个带有取消选项的无限循环?@deffis基本上是的。我曾被告知是“公正”线程,但在更高的层次上,它们的行为略有不同,但用途相同。不过,我可能在这一点上错了。我认为\u正在运行
应该是易失的
。否则,编译器可能会意识到它不是从当前线程修改的,并在循环开始之前只检查一次。TaskCreationOptions.longlunning
是必需的,不是吗?因此,使用TaskCreationOptions
和“DefaultScheduler”启动工厂.StartNew
比Task.Run
更可取。如果我错了,请纠正我。反应式扩展听起来很有希望,但目前我没有时间钻研另一个新工具。:)@SriramSakthivel:longlunning
只是一个提示。除非您在启动“无限循环”任务时已经在进行非常密集的并行处理,否则这是不必要的。和Task.Run
使用默认的计划程序。@stephenleary我不确定你所说的“它是不必要的”是什么意思。如果没有那个线程池,它将使用池的线程,对吗?启用这一功能将为任务创建专用线程,允许池中的线程处理其他cpu密集型的小操作?@ErwinMayer:我相信是这样,但我不能完全确定。
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