问题描述
编辑在我的问题中看到结尾处的标题问题,以解决这个问题。
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:
- 您继续
GetCustomersAsync
与仅在故障继续。 - 然后你继续继续,而不是
GetCustomersAsync
,下一个延续,只能在完成时运行。
- You continue
GetCustomersAsync
with "only on faulted" continuation. - 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中的链接任务与成功和故障处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!