gpt4 book ai didi

c# - 如何正确捕获多个异步方法调用中的异常?

转载 作者:行者123 更新时间:2023-12-02 02:17:35 25 4
gpt4 key购买 nike

我有一些异步方法:

public async Task<Object> MethodAsync()
{
return await MakeHttpRequestAsync();
}

我需要多次调用此方法。其中之一可以抛出异常。但我需要保留其他成功的方法调用中所有可能返回的对象。

选项 1:

Task t1 = MethodAsync();
Task t2 = MethodAsync();
try
{
Task.WaitAll(new Task[]{t1,t2});
}
catch(Exception e)
{
...
}
//are t1 and t2 finished execution here with success or exception?

选项 2:

Task t1 = MethodAsync();
Task t2 = MethodAsync();
try
{
t1.Wait()
}
catch(Exception e)
{
...
}

try
{
t2.Wait()
}
catch(Exception e)
{
...
}
//what happens if t2 throws exception before t1 finished?

还有其他选择吗?

编辑:考虑第三种选择:

    public async Task<Tuple<Object, Object>> MultipleAsyncCallsAsync(some arguments)
{
Object result1 = null, result2 = null;
try
{
result1 = await MethodAsync();
}
catch(Exception e)
{

}
try
{
result2 = await MethodAsync();
}
catch (Exception e)
{

}
return Tuple.Create(result1, result2);
}

编辑#2:

看起来第三个选项不起作用,但它是这样工作的:

public async Task<Tuple<object, object>> MultipleAsyncCallsAsync(some arguments)
{
object result1 = null, result2 = null;
Task<object> t1 = null, t2 = null;
t1 = Task.Run(()=> MethodAsync());
t2 = Task.Run(()=> MethodAsync());
try
{
result1 = await t1;
}
catch(Exception e)
{

}
try
{
result2 = await t2;
}
catch (Exception e)
{

}
return Tuple.Create(result1, result2);
}

最佳答案

将任务放入数组中并检查其状态,如下所示:

    var t1 = MethodAsync();
var t2 = MethodAsync();

var tasks = new[] {t1, t2};

try
{
await Task.WhenAll(tasks);
}
catch
{
var failedTasks = tasks.Where(t => t.IsFaulted);
var allExceptions = failedTasks.Select(t => t.Exception?.Flatten());
}

var results = tasks.Where(t => t.IsCompletedSuccessfully).Select(t => t.Result);

它的作用是等待所有任务,然后使用任务状态(使用 IsCompletedSuccessively 等)来获取所有成功完成的任务的结果。

您可以使用 IsFaulted 确定失败的任务,并使用任务 Exception 属性获取其异常。

如果您想在对 Task.WhenAll(..) 的调用完成之前捕获/检查异常,请将 MethodAsync 内的代码包装在 try/catch 中:

public async Task<Object> MethodAsync()
{
try
{
..
}
catch(Exception ex)
{
//handle or throw
return null;
}
}

或者,如果由于某种原因无法修改 MethodAsync,您可以使用以下方法将该方法包装在 try/catch 中:

Func<Task<Object>, Task<Object>> TryExecute = new Func<Task<Object>, Task<object>>(async t =>
{
try
{
return await t;
}
catch (Exception ex)
{
//handle exception
return null;
}
});

并像这样使用它:

    var t1 = TryExecute(MethodAsync());
var t2 = TryExecute(MethodAsyncF());

var tasks = new[] {t1, t2};

await Task.WhenAll(tasks);

关于c# - 如何正确捕获多个异步方法调用中的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66942489/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com