csharp中的链接任务与成功和故障处理程序 [英] Chaining Tasks in csharp with success and fault handler

查看:268
本文介绍了csharp中的链接任务与成功和故障处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑在我的问题中看到结尾处的标题问题,以解决这个问题。

Edit See the title "Problem" at the end within my question to crack this question down.

来自nodejs我们可以链接承诺,在C#我看到异步任务几乎相当。这是我的尝试。

Coming from nodejs where we could chain promises, in C# I'm seeing Async Tasks almost comparable. Here's my attempt.

编辑 - 我不能将我的uber级别的调用方法标记为 async as一个基于dll的库正在调用它

Edit - I can't mark my uber level caller methods as async as a dll based library is calling it

来电者对象

public void DoSomething(MyRequest request) 
{
    Delegate.Job1(request)
        .ContinueWith(Delegate.Job2)
        .ContinueWith(Fault, TaskContinuationOptions.OnlyOnFaulted)
        .ContinueWith(Result);
}

public void Result(Task<MyRequest> task)
{
    MyRequest request = task.Result;
    Console.Writeline(request.result1 + " " + request.result2);
}

public void Fault(Task<MyRequest> task)
{
   MyRequest request = task.Result;
   Console.Writeline(request.result);
}

代理对象

public async Task<MyRequest> Job1(MyRequest request) 
{
    var data = await remoteService.Service1Async();
    request.result1 = data;
    return request;
}

public async Task<MyRequest> Job2(Task<MyRequest> task)
{
    var data = await remoteService.Service2Async();
    request.result2 = data;
    return request;
}

问题

1)编辑(修复,链接的DLL到我的项目缺少它的链接dll) Task.Result (请求) 结果方法,另外 Status = Faulted

1) Edit (fixed, the linked dll to my project was missing it's linked dll) Task.Result (request) is coming as null in the Result method, Also Status = Faulted

2 )还有错误处理是否正确?我希望在委托方法中发生异常时才会调用Fault,否则应该跳过。

2) Also is Fault Handling correct? I'm expecting Fault to be only called when an exception occurs within the Delegate methods, otherwise it should skip.

2-b)另一个选项是在 result function(delete Fault function)if Task.status = RanTocompletion 并在那里分支成功或错误

2-b) Another option is check within the Result function (delete Fault function) if Task.status = RanTocompletion and branch there for success or fault

答案后编辑

如果我不能让我的控制器异步,该怎么办?

I've a gotcha, what if I can't make my controller async.

控制器

public void ICannotBeAsync()
{
    try
    {
        var r = await caller.DoSomething(request); // though I can use ContinueWith here, ???
    }
    catch(Exception e)
    {
        //exception handling
    }
}

来电者

public async Task DoSomethingAsync(MyRequest request)
{
     request.result1 = await delegateInstance.Job1(request);
     request.result2 = await delegateInstance.Job2(request);
     Console.Writeline(request.result1 + " " + request.result2);
     return result;
}






编辑2 - 基于VMAtm Edit,请查看OnlyOnFaulted(Fault)选项。


Edit 2 - based on VMAtm Edit, please review OnlyOnFaulted (Fault) option.

Delegate.Job1(request)
    .ContinueWith(_ => Delegate.Job2(request), TaskContinuationOptions.OnlyOnRanToCompletion)
    .ContinueWith(() => {request.result = Task.Exception; Fault(request);}, TaskContinuationOptions.OnlyOnFaulted)
    .ContinueWith(Result, TaskContinuationOptions.OnlyOnRanToCompletion);

问题 -

给它一个测试,下面的实际代码,没有一个 Result Fault 正在调用,虽然方法 GetCustomersAsync 成功返回。我的理解一切都停止在故障,因为它被标记为仅在故障上运行,执行停止在那里,

Gave it a test, actual code below, none of the Result or Fault is getting called, although the method GetCustomersAsync returned successfuly. My understanding everything stops at Fault because it's marked to run on Fault only, execution stops there and Result handler is not called.

Customer.GetCustomersAsync(request)
    .ContinueWith(_ => { Debug.WriteLine("not executing"); Fault(request); }, TaskContinuationOptions.OnlyOnFaulted)
    .ContinueWith(_ => { Debug.WriteLine("not executing either"); Result(request); }, TaskContinuationOptions.OnlyOnRanToCompletion);

编辑3 基于Evk的回答。

Task<Request> task = Customer.GetCustomersAsync(request);
task.ContinueWith(_ => Job2Async(request), TaskContinuationOptions.OnlyOnRanToCompletion);
task.ContinueWith(_ => Job3Async(request), TaskContinuationOptions.OnlyOnRanToCompletion);
task.ContinueWith(_ => Result(request), TaskContinuationOptions.OnlyOnRanToCompletion);
task.ContinueWith(t => { request.Result = t.Exception; Fault(request); }, TaskContinuationOptions.OnlyOnFaulted);


推荐答案

这里已经说了很多事情,所以我只能回答最后一个问题部分:

A lot of things has been said here, so I only answer to the last "Problem" section:

Customer.GetCustomersAsync(request)
    .ContinueWith(_ => { Debug.WriteLine("not executing"); Fault(request); }, TaskContinuationOptions.OnlyOnFaulted)
    .ContinueWith(_ => { Debug.WriteLine("not executing either"); Result(request); }, TaskContinuationOptions.OnlyOnRanToCompletion);

这里(原始示例)中的问题是以下情况发生:

Problem here (and in original example too) is that the following happens:


  1. 您继续 GetCustomersAsync 与仅在故障继续。

  2. 然后你继续继续,而不是 GetCustomersAsync ,下一个延续,只能在完成时运行。

  1. You continue GetCustomersAsync with "only on faulted" continuation.
  2. Then you continue that continuation, not GetCustomersAsync, with the next continuation, which can run only on completion.

结果是,当 GetCustomersAsync 失败时,两个连接只能执行 。要修复:

In result, both continations can execute only when GetCustomersAsync fails. To fix:

var request = Customer.GetCustomersAsync(request);
request.ContinueWith(_ => { Debug.WriteLine("not executing"); Fault(request); }, TaskContinuationOptions.OnlyOnFaulted);
request.ContinueWith(_ => { Debug.WriteLine("not executing either"); Result(request); }, TaskContinuationOptions.OnlyOnRanToCompletion);

注意,即使你不能改变一些方法的签名,它绝对必须返回void,你仍然可以将其标记为异步:

Note that even if you cannot change signature of some method and it absolutely must return void, you still can mark it as async:

public async void DoSomethingAsync(MyRequest request)
{
     try {
         await Customer.GetCustomersAsync(request);
         Result(request);      
     }
     catch (Exception ex) {
         Fault(request);
     }
}

这篇关于csharp中的链接任务与成功和故障处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆