Edit See the title "Problem" at the end within my question to crack this question down.
Coming from nodejs where we could chain promises, in C# I'm seeing Async Tasks almost comparable. Here's my attempt.
Edit - I can't mark my uber level caller methods as async
as a dll based library is calling it
Caller object
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);
}
Delegate Object
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;
}
Problem:
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) 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) Another option is check within the Result
function (delete Fault
function) if Task.status = RanTocompletion
and branch there for success or fault
Edit after the answer
I've a gotcha, what if I can't make my controller async.
Controller
public void ICannotBeAsync()
{
try
{
var r = await caller.DoSomething(request); // though I can use ContinueWith here, ???
}
catch(Exception e)
{
//exception handling
}
}
Caller
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;
}
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);
Problem -
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);
Edit 3 Building on Evk's answer.
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);