Изменить См. заголовок «Проблема» в конце моего вопроса, чтобы решить этот вопрос.
Исходя из nodejs, где мы могли связывать промисы, в C# я вижу, что асинхронные задачи почти сопоставимы. Вот моя попытка.
Редактировать. Я не могу пометить свои методы вызова уровня uber как async
, так как их вызывает библиотека на основе dll
Вызывающий объект
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
(запрос) приходит как null в методе Result
, также Status = Faulted
2) Также корректна ли обработка ошибок? Я ожидаю, что Fault будет вызываться только тогда, когда в методах Delegate возникает исключение, в противном случае его следует пропустить.
2-b) Другой вариант - проверить в функции Result
(удалить функцию Fault
), если Task.status = RanTocompletion
, и перейти туда для успеха или ошибки
Редактировать после ответа
У меня есть проблема, что, если я не могу сделать свой контроллер асинхронным.
Контроллер
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, проверьте параметр OnlyOnFaulted (ошибка).
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
успешно вернулся. Насколько я понимаю, все останавливается на Fault
, потому что он помечен для запуска только на Fault
, выполнение останавливается там, а обработчик Result
не вызывается.
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);
chained ContinueWith async operations
с опциейOnlyOnRanToCompletion
в строку № 2 вашего кода и нажмуFault
(строка 2) иResult
(строка 3) вниз, будет ли это работать как положено, т.е. задачи будет продолжать выполнение до конца в случае успеха, а в случае неудачи он сразу перейдет к ошибке, пропуская любые промежуточные операции. 08.02.2017t.Exception
, чтобы сообщить звонящему Uber или запрашивающим клиентам, что пошло не так. 08.02.2017GetCustomersAsync
,Job2Async
иJob3Async
. Это значит, что я должен отказаться от этого маршрута??? 08.02.2017await
. 08.02.2017async await
сейчас, поворотным моментом стало то, что вы сказали, что мой метод может оставить недействительным, я не могу изменить свой контракт с вызывающими абонентами uber, запрос, который я получаю, в основном является шаблоном наблюдателя, и в результате/ошибке я уведомить uber о результате или исключении. Я попробовал предложенный вами маршрут для проверки IsCompleted и isFaulted, но он внес шум в мой код. await и async чисты и даже лучше, чемContinueWith
, и я с удовольствием использую их, сохраняя при этом свой метод недействительным. Спасибо за вашу замечательную помощь. 08.02.2017async void
используется только для обработчиков асинхронных событий, и его следует избегать, однако, если вы не можете изменить подпись, это вариант. Возможно, вам потребуется добавитьConfigureAwait(false)
к вашимawait
заявлениям. 08.02.2017