English 中文(简体)
任务 模式和错误/例外/出色处理
原标题:Task Asynchronous Pattern and error/exception/cancellation handling
  • 时间:2012-04-08 14:27:47
  •  标签:
  • c#
  • exception

我经常有申请,高级职能部门从事类似工作。

public Result5 ProcessAll() {
    var result1 = Process1();
    var result2 = Process2();
    var result3 = Process3(result1);
    var result4 = Process4(result1, result2);
    return Process5(result1, result2, result3, result4);
}

该进程* 职能的共同之处是:

  • IO Bound (database, filesystem, webservice)
  • Might throw exceptions which is just propagated up in the call stack
  • Might return error for some non-exceptional errors which should just stop processing and return

The top level function is also running on a background thread which can be canceled. This means that the full implementation looks like

public Result5 ProcessAll(CancellationToken cancellationToken) {
    Result1 result1 = Process1();

    if (result1 == null)
        return null;
    cancellationToken.ThrowIfCancellationRequested();

    Result2 result2 = Process2();

    if (result2 == null)
        return null;
    cancellationToken.ThrowIfCancellationRequested();

    Result3 result3 = Process3(result1);

    if (result3 == null)
        return null;
    cancellationToken.ThrowIfCancellationRequested();

    Result4 result4 = Process4(result1, result2);

    if (result4 == null)
        return null;
    cancellationToken.ThrowIfCancellationRequested();

    return Process5(result1, result2, result3, result4);
}

现在让我假设,我需要尽可能同步地加快步伐。

还假设该进程* 能够执行“任务同步模式”,并使用国际海事组织完成港口或类似港口。

I have not been able to find any good pattern for this.
If I ignore error/exception/cancellation it would look like this.

public Result5 ProcessAll(CancellationToken cancellationToken) {
    Task<Result1> task1 = Process1Async();
    Task<Result2> task2 = Process2Async();

    Task<Result3> task3 = task1.ContinueWith(_ => Process3Async(task1.Result)).Unwrap();

    Task<Result4> task4 = Task.Factory.ContinueWhenAll(new[] { task1, task2 }, 
                                                       _ => Process4Async(task1.Result, task2.Result)).Unwrap();

    // This will trigger all exceptions captured
    Task.WaitAll(new[] { task1, task2, task3, task4 });

    return Process5(task1.Result, task2.Result, task3.Result, task4.Result);
}

(我知道,可以优化这项工作,如执行任务4 同步,瓦伊特·All只是必要的,但我只是在这里显示一种模式)

如果我现在试图处理错误和例外情形,那么我可以认为:

public Result ProcessAll(CancellationToken cancellationToken) {
    Task<Result1> task1 = Process1Async();
    Task<Result2> task2 = Process2Async();

    // Process 3 should not run if task1 or task2 failed or returned error
    Task<Result3> task3 = task1.ContinueWith(_ => {
         if (task1.IsFaulted || task1.Result == null)
             return null;
         if (task2.IsFaulted || (task2.IsCompleted && task2.Result == null)
             return null;
         return Process3Async(task1.Result);
    }).Unwrap();

    // Process4 should not start if any of Process1,Process2 or Process3 returned error or throw exception
    Task<Result4> task4 = Task.Factory.ContinueWhenAll(new[] { task1, task2 }, _ => {
                                                       if (task1.Faulted || task1.Result == null)
                                                           return null;
                                                       if (task2.Faulted || task2.Result == null)
                                                           return null;
                                                       if (task3.Faulted || (task3.IsCompleted && task3.Result == null))
                                                           return null;
                                                       return Process4Async(task1.Result, task2.Result)).Unwrap();

    Task.WaitAll(new[] { task1, task2, task3, task4 });
    if (task1.Result == null || 
        task2.Result == null || 
        task3.Result == null || 
        task4.Result == null)
        return null;
    return Process5(task1.Result, task2.Result, task3.Result, task4.Result);
}

现在,我需要进行取消检查:-

My question now is:
All these checks for failures, errors and cancellation in earlier tasks becomes error prone and is not very scalable. Am I missing something important here and doing it the wrong way?

问题回答

只有当以前所有进程都已完成时,你才能启动进程3、4和5。 因此,你不需要为他们执行任务。 你们只需要利用头两个任务,使问题更加容易。 如果你选择开始执行这些任务,那么这项任务将永远等待前任,消除任何平行的做法。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签