将异步 lambda 包装到异步方法
本文关键字:异步方法 包装 lambda 异步 | 更新日期: 2023-09-27 18:33:47
我正在尝试将我的Operations Contracts
包装到 try-catch 块。问题是我的 EF 上下文在同一时间范围内被破坏。我猜问题编译器不知道该怎么做。此外,我的捕获块不处理任何异常。对不起我的英语,我希望我的代码显示我的意思:
private static async Task<T> SurroundWithTryCatch<T>(Action t, T response) where T : BaseResponse
{
try
{
await Task.Run(t);
}
catch (Exception e)
{
response.Success = false;
response.Errors.Add(e.Message);
}
return response;
}
public async Task<CreateResponse> CreateAsync(CreateRequest request)
{
var response = new CreateResponse();
return await SurroundWithTryCatch(async delegate
{
var newUser = new ApplicationUser { UserName = request.UserName, Email = request.Email };
await Database.UserManager.CreateAsync(newUser, request.Password);
//Some another logic...
await Database.CommitAsync();
}, response);
}
第二行CreateAsync
方法中的问题。 UserManager
之前被GC清理过。所以我有ObjectDisposedException
. Database
是IUnitOfWork
实现,由Autofac
注入。
您正在打破await
链 - t
不再返回任务。由于您不再有任务,因此执行将在第一个await
之后继续,而不是在整个方法完成后。将await
视为return
- 如果您不返回(并await
/等待)任务,您将失去同步的机会。
相反,您希望传递 Func<Task>
并直接等待它:
private static async Task<T> SurroundWithTryCatch<T>(Func<Task> t, T response) where T : BaseResponse
{
try
{
await t();
}
catch (Exception e)
{
response.Success = false;
response.Errors.Add(e.Message);
}
return response;
}
public async Task<CreateResponse> CreateAsync(CreateRequest request)
{
var response = new CreateResponse();
return await SurroundWithTryCatch(async () =>
{
var newUser = new ApplicationUser { UserName = request.UserName, Email = request.Email };
await Database.UserManager.CreateAsync(newUser, request.Password);
//Some another logic...
await Database.CommitAsync();
}, response);
}
Task.Run
也可以工作,但您可能不希望这样做 - 您的代码是异步的,并且(猜测)您正在 ASP.NET 请求中运行,因此启动任务只是为了等待另一个任务的结果没有任何好处。 Task.Run
用于在单独的线程中执行 CPU 工作,这通常是您在 ASP.NET 中避免的。