Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何停止多个并行。对于具有CancellationToken的循环_C#_Wpf_Parallel.for - Fatal编程技术网

C# 如何停止多个并行。对于具有CancellationToken的循环

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

我正在用C#和WPF开发一个应用程序。我使用3个嵌套的
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这样做是非常好的。