C# 由于同一范围内的另一个任务抛出异常而处于不确定状态的任务的命运是什么?

C# 由于同一范围内的另一个任务抛出异常而处于不确定状态的任务的命运是什么?,c#,exception,task-parallel-library,C#,Exception,Task Parallel Library,在情况1中,taska和taskb在同一范围内taska已经尘埃落定,我们过早地离开了这个范围。taskb会怎么样?换句话说:机械地说,框架/操作系统如何知道如何杀死taskb或以其他方式处理它? 在情况2中,我们不会过早地离开作用域,因此taskb会按预期完成其任务。这一点也不奇怪 (目前真正的问题是在控制台应用程序中找到最干净的方法来处理ctrl+c,该应用程序使用两个菊花链TPL数据流操作块,第二个操作块上的MaxDegreeOfParallelism设置为processor count。

在情况1中,
taska
taskb
在同一范围内
taska
已经尘埃落定,我们过早地离开了这个范围。
taskb
会怎么样?换句话说:机械地说,框架/操作系统如何知道如何杀死
taskb
或以其他方式处理它?

在情况2中,我们不会过早地离开作用域,因此
taskb
会按预期完成其任务。这一点也不奇怪

(目前真正的问题是在控制台应用程序中找到最干净的方法来处理ctrl+c,该应用程序使用两个菊花链TPL数据流操作块,第二个操作块上的MaxDegreeOfParallelism设置为processor count。这是对该概念的最低限度的重复。等待(或不等待)的智慧(或愚蠢)是什么对于所有完成,如果用户想要中止?)

inta=0;
int b=0;
int counta=0;
int countb=0;
Task taska=Task.Run(()=>
{
Random rng=新随机((int)DateTime.UtcNow.Ticks);
对于(int i=0;i<100000000;i++)
{
a+=下一个(1000000)-500000的rng;
counta++;
如果(counta>100000){抛出新的NotImplementedException();}
}
});
Task taskb=Task.Run(()=>
{
Random rng=新随机((int)DateTime.UtcNow.Ticks);
对于(int i=0;i<100000000;i++)
{
b+=下一个(1000000)-500000的rng;
countb++;
}
});
尝试
{
Task.WaitAll(新任务[]{taska});//情况1
//Task.WaitAll(新任务[]{taska,taskb});//情况2
}
捕获(例外)
{
控制台写入线(a);
控制台写入线(b);
控制台写入线(counta);
控制台写入线(countb);
}
输出:

-30873531
-477919899
100001
3678224

编辑:这个问题类似于链接的问题,但我觉得它对未来的搜索者仍然有帮助,因为它关注的是关于范围如何影响(或不影响)结果的(看似合理但不正确的)看法。

更糟的是,我的任务可能正在启动带有Process.Start.tasks的external.exe,它们不会被终止,只是停止运行(除非进程退出,此时所有任务都会不规则地结束)。未处理的异常终止常规任务流。这里没有与任务相关的“范围”,也没有
taska
taskb
之间的任何关系。如果您不等待
taskb
完成,它将继续自己愉快地运行。顺便说一句,如果您将“task”替换为“thread that has
IsBackground
设置为
true
”,以上所有内容或多或少都会保持不变。请注意,以下两项都不会影响
taskb
的运行:变量
taskb
使用超出范围(这些已在保持活动状态的闭包中捕获)或变量
taskb
本身超出范围(这不会释放运行代码的线程,并且
Task
在与其关联的委托运行期间保持活动状态)这就是为什么
Task
s有一个内置的协作取消机制(
CancellationToken
)是一件好事,理想情况下,如果您不打算直接退出进程,您应该使用该机制。“框架/OS如何知道如何杀死taskb或以其他方式使用它?”--没有。如上所述,任务彼此独立,除非您做了明确的事情使其独立。例如,如果第一个任务引发异常,您将取消第二个任务。请参阅重复项。任务不是线程,它们表示需要在线程池线程上运行的作业。在其他语言中,您可以将其称为
承诺
或a
future
。名为
taska
的作业与名为
taskb
的作业没有任何关联,因此当作业
taska
失败时,
taskb
将继续运行,直到应用程序终止