gpt4 book ai didi

c# - 在 catch 子句中禁止等待。寻找解决办法

转载 作者:太空狗 更新时间:2023-10-29 17:53:43 25 4
gpt4 key购买 nike

我知道 await 不能用在 catch 子句中。但是直到现在我还没有真正遇到过与此相关的问题......

基本上我有一个层负责接收传入的请求、处理它们、从中构建消息并将消息传递给负责发送消息的另一个层。

如果在消息发送过程中出现问题,将抛出自定义异常,并由消息发送层捕获。此时,这条消息的失败记录应该被插入到数据库中(需要一些时间,所以是异步的),异常应该传播到上层,上层负责向发出请求的客户端发送错误响应.

下面是一些非常简化的代码,用于说明目的:

public async Task ProcessRequestAsync(Request req)
{
int statusCode = 0;

try
{
await SendMessageAsync(new Message(req));
}
catch(MyCustomException ex)
{
statusCode = ex.ErrorCode;
}

await SendReponseToClientAsync(req, statusCode);
}


public async Task SendMessageAsync(Message msg)
{
try
{
// Some async operations done here
}
catch (MyCustomException ex)
{
await InsertFailureForMessageInDbAsync(msg, ex.ErrorCode); // CAN'T DO THAT
throw;
}
}

当然,请求处理层对数据库一无所知,它只是负责构建消息,将消息传递给消息处理层,并向客户端发送响应(正面或负面)。

所以我认为这是有道理的......如果发生异常,我的“业务”层想在数据库中插入一条失败记录并重新抛出异常,以便“请求”处理层可以做必要的事情(在这种情况下,将否定响应发送回客户端)。

不应该这样使用异常吗?这对我来说似乎很干净,但我不能在 catch 子句中执行此等待这一事实让我认为设计中可能存在代码味道(即使我的想法是在一层中处理异常然后将其重新抛出上层也做一些不同的处理,在我看来这正是异常的目的。

有什么想法吗?

谢谢!

最佳答案

我也遇到过几次。

正如 Rafael 评论的那样,您可以忽略 InsertFailureForMessageInDbAsync 的结果:

public async Task SendMessageAsync(Message msg)
{
try
{
// Some async operations done here
}
catch (MyCustomException ex)
{
var _ = InsertFailureForMessageInDbAsync(msg, ex.ErrorCode);
throw;
}
}

请注意,默认情况下将忽略来自 InsertFailureForMessageInDbAsync 的任何异常。

你的另一个选择更复杂:

public async Task DoSendMessageAsync(Message msg)
{
// Some async operations done here
}

public async Task SendMessageAsync(Message msg)
{
var task = DoSendMessageAsync(msg);
MyCustomException exception = null;
try
{
await task;
return;
}
catch (MyCustomException ex)
{
exception = ex;
}

await Task.WhenAll(task, InsertFailureForMessageInDbAsync(msg, exception.ErrorCode));
}

这将异步处理异常并返回一个具有真实AggregateExptionTask(如果InsertFailureForMessageInDbAsync 抛出一个异常,则包含两个异常)。

不幸的是,await 将忽略第二个异常。如果您真的希望传递所有异常,可以将最后一行 (await Task.WhenAll...) 替换为如下内容:

Exception exception2 = null;
try
{
await InsertFailureForMessageInDbAsync(msg, exception.ErrorCode);
}
catch (Exception ex)
{
exception2 = ex;
}

if (exception2 == null)
throw new AggregateException(exception);
else
throw new AggregateException(exception, exception2);

但这相当复杂,而且并不是您想要重复的那种模式。如果可能的话,我会按照 Rafael 的建议忽略日志记录结果。

关于c# - 在 catch 子句中禁止等待。寻找解决办法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13888448/

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