C# 如何停止多个并行。对于具有CancellationToken的循环
我正在用C#和WPF开发一个应用程序。我使用3个嵌套的C# 如何停止多个并行。对于具有CancellationToken的循环,c#,wpf,parallel.for,C#,Wpf,Parallel.for,我正在用C#和WPF开发一个应用程序。我使用3个嵌套的Parallel.For循环,如下所示。当我Cancel()标记时,循环开始抛出importabledexception但是,我无法捕获importabledexception。我要说的是aggregateeexception 我想要的是,停止所有的并行.Fors,捕捉importabledexception并做一些其他事情 这是代码 private int _loopCount1 = 100; private int _lo
Parallel.For
循环,如下所示。当我Cancel()
标记时,循环开始抛出importabledexception
但是,我无法捕获importabledexception
。我要说的是aggregateeexception
我想要的是,停止所有的并行.For
s,捕捉importabledexception
并做一些其他事情
这是代码
private int _loopCount1 = 100;
private int _loopCount2 = 200;
private int _loopCount3 = 10000;
private CancellationToken _cToken;
private CancellationTokenSource _cSource;
private void Init()
{
_cSource = new CancellationTokenSource();
_cToken = new CancellationToken();
_cToken = _cSource.Token;
try
{
DoTheWork();
}
catch (ImportAbortedException)
{
///
}
catch (Exception)
{
}
}
private void StopAllLoops()
{
_cSource.Cancel();
}
private void DoTheWork()
{
Parallel.For(0, _loopCount1, i =>
{
if (CheckIfCanceled())
throw new ImportAbortedException("process aborted!");
// do a few calculations here.
Parallel.For(0, _loopCount2, j =>
{
if (CheckIfCanceled())
throw new ImportAbortedException("process aborted!");
// do a few calculations here.
Parallel.For(0, _loopCount3, k =>
{
if (CheckIfCanceled())
throw new ImportAbortedException("process aborted!");
// do some other process here.
});
});
});
}
private bool CheckIfCanceled()
{
return _cToken.IsCancellationRequested;
}
Parallel.For的ParallelOptions属性有一个CancellationToken属性,您可以传递它,因此当取消取消令牌时,将停止的并行并生成OperationCanceledException
我会避免使用
并行。对于完全使用微软的反应式框架(NuGet“Rx Main”和“Rx WPF”)。您可以使用它来整洁地处理所有并行处理,并将结果整理回UI线程
您的代码如下所示:
private IDisposable DoTheWork()
{
var query =
from i in Observable.Range(0, _loopCount1)
from x in Observable.Start(() => SomeCalculation1(i))
from j in Observable.Range(0, _loopCount2)
from y in Observable.Start(() => SomeCalculation2(i, j))
from k in Observable.Range(0, _loopCount3)
from z in Observable.Start(() => SomeCalculation3(i, j, k))
select new { x, y, z };
return
query
.ObserveOnDispatcher()
.Subscribe(w =>
{
/* Do something with w.x, w.y, w.z */
});
}
var subscription = DoTheWork();
你可以这样称呼它:
private IDisposable DoTheWork()
{
var query =
from i in Observable.Range(0, _loopCount1)
from x in Observable.Start(() => SomeCalculation1(i))
from j in Observable.Range(0, _loopCount2)
from y in Observable.Start(() => SomeCalculation2(i, j))
from k in Observable.Range(0, _loopCount3)
from z in Observable.Start(() => SomeCalculation3(i, j, k))
select new { x, y, z };
return
query
.ObserveOnDispatcher()
.Subscribe(w =>
{
/* Do something with w.x, w.y, w.z */
});
}
var subscription = DoTheWork();
要取消,只需执行以下操作:
subscription.Dispose();
它是多线程、UI安全的,并且可以轻松取消。取消任务是一项非常正常的操作。首先为什么要抛出异常?因为我想知道计算过程中抛出了异常还是导入被取消了。所以,你说我无法捕获ImportableDexception。我只能捕获CancellationToken引发的异常?(OperationCanceledException)您可以捕获ImportableOrtedException,但是为什么不使用内置功能来取消操作呢?您可以共享ParallelOptions选项,从而减少代码量。我放弃了使用ImportableDexception的想法,并遵循了您的解决方案。非常感谢。谢谢你的回答,但我更喜欢使用Parallel.for。因为所有的项目都已经编写和测试过了。这就是为什么我不能做出巨大的改变:(@cKNet-不用担心,但你必须同意,Rx这样做是非常好的。