使用带有条件延续的任务

dan*_*dan 31 c# .net-4.0 task-parallel-library

我对如何使用条件Continuations的任务感到困惑.

如果我有一个任务,然后我想继续处理成功和错误的任务,然后等待那些完成.

void FunctionThrows() {throw new Exception("faulted");}

static void MyTest()
{

    var taskThrows = Task.Factory.StartNew(() => FunctionThrows());

    var onSuccess = taskThrows.ContinueWith(
                          prev => Console.WriteLine("success"), 
                          TaskContinuationOptions.OnlyOnRanToCompleted);

    var onError = taskThrows.ContinueWith(
                          prev => Console.WriteLine(prev.Exception),
                          TaskContinuationOptions.OnlyOnFaulted);

    //so far, so good



    //this throws because onSuccess was cancelled before it was started
    Task.WaitAll(onSuccess, onError);
}
Run Code Online (Sandbox Code Playgroud)

这是执行任务成功/失败分支的首选方式吗?另外,我应该如何加入所有这些任务,假设我已经创建了一长串的延续,每个延续都有自己的错误处理.

  //for example
  var task1 = Task.Factory.StartNew(() => ...)
  var task1Error = task1.ContinueWith(  //on faulted
  var task2  = task1.ContinueWith(      //on success
  var task2Error = task2.ContinueWith(  //on faulted
  var task3 = task2.ContinueWith(       //on success
  //etc
Run Code Online (Sandbox Code Playgroud)

调用WaitAll这些总是抛出,因为一些延续将被取消TaskContinuationOptions,并且调用Wait取消的任务抛出.如何在没有得到"任务被取消"异常的情况下加入这些例外"?

Bry*_*Ray 11

我认为你的主要问题是,你告诉这两个任务是"等待"你的电话

Task.WaitAll(onSuccess, onError);
Run Code Online (Sandbox Code Playgroud)

将自动为您设置onSuccessonError延续,并将其前期任务完成执行.

如果你只是替换你Task.WaitAll(...),taskThrows.Start();我相信你会得到所需的输出.

这是我放在一起的一个例子:

class Program
{
    static int DivideBy(int divisor) 
    { 
      Thread.Sleep(2000);
      return 10 / divisor; 
    }

    static void Main(string[] args)
    {
        const int value = 0;

        var exceptionTask = new Task<int>(() => DivideBy(value));

        exceptionTask.ContinueWith(result => Console.WriteLine("Faulted ..."), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent);
        exceptionTask.ContinueWith(result => Console.WriteLine("Success ..."), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent);

        exceptionTask.Start();

        try
        {
            exceptionTask.Wait();
        }
        catch (AggregateException ex)
        {
            Console.WriteLine("Exception: {0}", ex.InnerException.Message);
        }

        Console.WriteLine("Press <Enter> to continue ...");
        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)