Я выполняю рефакторинг старого кода, который выполняет синхронные http-запросы и возвращает объект Callback с событиями успеха и сбоя.Как правильно обернуть код в async / await?
Я добавил класс HttpClient и использую метод SendAsync, для которого я ожидаю, но я не уверен, как правильно сделать переход из await в события.Я добавил асинхронный void метод Execute в класс, но это не похоже на правильный способ обработки - избегайте асинхронного void.Ниже приведено более подробное объяснение в (краткой версии) кода.
public class HttpExecutor(){
public event Action<string> Succeed;
public event Action<ErrorType, string> Failed;
private bool isExecuting;
//I know that async void is not the best because of exceptions
//and code smell when it is not event handler
public async void Execute()
{
if (isExecuting) return;
isExecuting = true;
cancellationTokenSource = new CancellationTokenSource();
try
{
httpResponseMessage =
await httpService.SendAsync(requestData, cancellationTokenSource.Token).ConfigureAwait(false);
var responseString = string.Empty;
if (httpResponseMessage.Content != null)
{
responseString = await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
}
if (httpResponseMessage.IsSuccessStatusCode)
{
Succeed?.Invoke(responseString);
return;
}
Failed?.Invoke(httpResponseMessage.GetErrorType(),
$"{httpResponseMessage.ReasonPhrase}\n{responseString}");
}
//Catch all exceptions separately
catch(...){
}
finally
{
Dispose();
}
}
}
public class UserService(){
public CallbackObject<User> GetUser(){
var executor = new HttpExecutor(new RequestData());
//CallbackObject has also success and fail, and it hooks to executor events, deserializes string into object and sends model by his own events.
var callback = new CallbackObject<User>(executor);
executor.Execute();//in normal case called when all code has possibility to hook into event
return callback;
}
}
Я чувствую, что должен изменить метод на: public async Task ExecuteAsync(){...}
, но тогда мне нужно будет взять поток из пула потоков, выполнив: Task.Run(()=>executor.ExecuteAsync());
Кажется, что это немного пожар и забыть, но с обратными вызовами (я жду ответа от сети).Как правильно с этим справиться?