C# 通过取消安装请求不';我似乎没有任何例外
我有以下代码:C# 通过取消安装请求不';我似乎没有任何例外,c#,multithreading,task-parallel-library,task,cancellationtokensource,C#,Multithreading,Task Parallel Library,Task,Cancellationtokensource,我有以下代码: CancellationTokenSource cts = new CancellationTokenSource(); ParallelOptions po = new ParallelOptions(); po.CancellationToken = cts.Token; Task.Factory.StartNew(() => { if (Console.ReadKey().KeyChar == 'c') cts.Cancel();
CancellationTokenSource cts = new CancellationTokenSource();
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
Task.Factory.StartNew(() =>
{
if (Console.ReadKey().KeyChar == 'c')
cts.Cancel();
Console.WriteLine("press any key to exit");
});
Parallel.ForEach(list, po, (algo) =>
{
algo.Compute(); // this compute lasts 1 minute
Console.WriteLine("this job is finished");
po.CancellationToken.ThrowIfCancellationRequested();
});
列表
包含的元素很少。
当我按下“c”键时,所有的Compute
方法都已启动
当我按下“c”键时,不会引发异常。每个Compute
方法继续执行,直到其正常结束
当我按下“c”键时,我想停止/杀死所有剩余的
计算方法。取消不是这样工作的。这不像调用Thread.Abort()
立即终止线程
对于序列中的每个元素,您的代码执行以下操作:
调用Compute()
方法
等待它完成
向控制台写入关于完成的信息
检查是否请求取消,如果请求取消,则抛出OperationCanceledException
为了取消某些任务,您需要将CancellationToken
传递给被调用的方法。
也许,将长时间运行的计算组织为一个循环,并检查是否在每个步骤都请求取消以尽快停止它是值得的
例如,在Compute()
方法中,可以执行如下检查:
private void Compute(CancellationToken ct)
{
while (true)
{
ComputeNextStep();
ct.ThrowIfCancellationRequested();
}
}
使用po.CancellationToken.IsCancellationRequested查看取消操作,并使用停止Parallel.ForEach
:
void Compute(CancellationToken token, ParallelLoopState loopState)
{
bool more = true;
while (more)
{
if (token.IsCancellationRequested)
{
// stop Parallel.ForEach ASAP
loopState.Stop();
return;
}
// do the calc step
}
}
// ...
CancellationTokenSource cts = new CancellationTokenSource();
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
Task.Factory.StartNew(() =>
{
if (Console.ReadKey().KeyChar == 'c')
cts.Cancel();
Console.WriteLine("press any key to exit");
});
Parallel.ForEach(list, po, (algo, loopState) =>
{
algo.Compute(po.CancellationToken, loopState); // this compute lasts 1 minute
Console.WriteLine("this job is finished");
});
// observe the cancellation again and throw after Parallel.ForEach
po.CancellationToken.ThrowIfCancellationRequested();
我认为您需要手动处理工作单元
方法中的取消`一旦线程启动,它将自行处理。你需要从线程中抛出它。是的,你必须将取消令牌传递给algo.Compute()
,并在该方法的循环中检查它。只需将magicThrowIfCancellationRequested
行放在源代码中的某个地方,就不会发生任何事情。这一行也需要执行。我要补充一点,
CancellationToken`的点是为新线程播种的进程和线程本身之间的连接线程(双关语)。如果种子设定进程可以取消线程,则不需要取消令牌,对吗?:)因此,CancellationToken
用于发送信号。你需要处理信号还有一件事。。。这也是一个很好的设计,因为在取消之前,您的代码可能需要处理一些对象或句柄。仅仅从外部“杀死”线程就可能产生内存/资源问题。最好让线程处理取消。