Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.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#Task.WaitAll()取消并进行错误处理_C#_Exception Handling_Synchronization_Task_Aggregateexception - Fatal编程技术网

C#Task.WaitAll()取消并进行错误处理

C#Task.WaitAll()取消并进行错误处理,c#,exception-handling,synchronization,task,aggregateexception,C#,Exception Handling,Synchronization,Task,Aggregateexception,我有个问题。 我尝试运行多个长时间运行的任务。如果其中一个失败,我想取消所有其他任务,并获得失败异常。 下面给出的例子。 我想捕获AggregateException和 throw new Exception("FailureTask"); 但我捕获的不是AggregateException,而是OperationCanceledException,因为我想取消所有其他任务 [TestMethod] public void TestParallelTaskCancelatio

我有个问题。 我尝试运行多个长时间运行的任务。如果其中一个失败,我想取消所有其他任务,并获得失败异常。 下面给出的例子。 我想捕获AggregateException和

 throw new Exception("FailureTask");
但我捕获的不是AggregateException,而是OperationCanceledException,因为我想取消所有其他任务

    [TestMethod]
    public void TestParallelTaskCancelation()
    {
        var cancellationTokenSource = new CancellationTokenSource();
        Task[] tasks =
        {
            Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
            Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
            Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
            Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
            Task.Factory.StartNew(FailureTask, cancellationTokenSource, cancellationTokenSource.Token)
        };

        try
        {
            Task.WaitAll(tasks, cancellationTokenSource.Token);
        }
        catch (OperationCanceledException e)
        {
            Console.WriteLine(e.GetaAllMessages());
        }
        catch (AggregateException e)
        {
            Console.WriteLine(e.GetaAllMessages());
        }
    }

    private void DummyTask(object o)
    {
        var cancellationToken = (CancellationTokenSource)o;
        while (true)
        {
            Thread.Sleep(10000);
            if (cancellationToken.IsCancellationRequested)
            {
                cancellationToken.Token.ThrowIfCancellationRequested();
            }
        }
    }

    private void FailureTask(object o)
    {
        var cancellationToken = (CancellationTokenSource)o;

        var executionTask = Task.Factory.StartNew(() =>
        {
            Thread.Sleep(1000);
            throw new Exception("FailureTask");
        }, cancellationToken.Token);

        executionTask.ContinueWith(t =>
        {
            cancellationToken.Cancel(false);
            throw new Exception(t.Exception.GetaAllMessages());
        }, TaskContinuationOptions.OnlyOnFaulted);

        if (executionTask.Wait(10 * 1000, cancellationToken.Token)) return;
        //timeout !!!
        throw new Exception("The limit 'Max Seconds Per Query' has been exceeded!!!");
    }`

请提供帮助。

您应该使用throw
aggregateeexception
构造函数,而不仅仅是
Exception

throw new AggregateException ("FailureTask");
这对我有用

public static async void TestParallelTaskCancelation()
    {
        var cancellationTokenSource = new CancellationTokenSource();
        Task[] tasks =
        {
        Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
        Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
        Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
        Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
        Task.Factory.StartNew(FailureTask, cancellationTokenSource, cancellationTokenSource.Token)
        };

        try
        {
           await Task.WhenAll(tasks);
        }
        catch (OperationCanceledException e)
        {
            Console.WriteLine(e.ToString());
        }
        catch (AggregateException e)
        {
            Console.WriteLine(e.ToString());
        }
    }

这是正确的答案:-)你比我快…,你不必取消等待,因为你想等待所有其他线程被取消。否,如果一个线程失败,我需要取消所有其他线程。当FailureTask失败时,所有其他线程都将使用CancellationToken取消。将通过cancellationTokenSource取消。使用Task.WaitAll(tasks,cancellationTokenSource.Token),您只需取消等待,而不是您之前创建的任务。这就成功了。问题是为什么。删除
cancellationTokenSource.Token
form
Task.WaitAll()
。您将抛出一个
异常
,它是所有异常的基类<代码>操作取消异常和
聚合异常
源自
异常
。您的异常永远不会被捕获,因为您只捕获更具体的异常。要捕获一个
AggregateException
,您必须抛出一个
AggregateException
。如果两个或多个任务同时失败怎么办。那么我会抓住哪一个例外?据我所知,AggregateException应该包括已取消任务的取消异常和其他任务的异常;不起作用。即使仅捕获(基本)异常也会捕获OperationCanceledException。@Thomaschneiter这不是100%正确。“OperationCanceledException”将从Taks.WaitAll发出,因为它是cancel。如果取消该任务,将抛出AggregateException。