gpt4 book ai didi

c# - Using block 中的异步

转载 作者:可可西里 更新时间:2023-11-01 08:24:22 27 4
gpt4 key购买 nike

我在 C# 中有以下异步函数:

private async Task<T> CallDatabaseAsync<T>(Func<SqlConnection, Task<T>> execAsync)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
return await execAsync(connection);
}
}

它允许执行任何异步函数 execAsync,该函数将 SQL 连接作为参数并使用它来进行数据库调用,方法是提供连接对象并确保其正确关闭。

然后从 WebApi Controller 中的操作调用此函数,如下所示:

public async Task<HttpResponseMessage> MyAction()
{
Func<SqlConnection, Task<SomeType>> execAsync = (function definition here);
await CallDatabaseAsync(execAsync);
return Request.CreateResponse(HttpStatusCode.OK);
}

这一切都很好,直到我对 WebApi 操作进行了一项更改:我从中删除了 async/await。我不想等待数据库调用,因为我不关心结果,我只想触发并忘记。

这似乎仍然可以正常工作——也就是说,如果我在浏览器中导航到操作的 URL,我不会收到任何错误。但实际上有一个问题——数据库连接没有关闭。调用操作 100 次后,连接池达到其默认限制 100,应用程序停止工作。

我做错了什么?我需要在 CallDatabaseAsync() 中更改什么,以便它绝对确保连接将关闭,无论如何?

最佳答案

在 ASP.NET 中,每个请求都有一个特殊的 SynchronizationContext .此同步上下文使在 await 之后运行的代码使用与原始请求相同的“上下文”。例如,如果 await 之后的代码访问当前的 HttpContext ,它将访问属于同一 ASP.NET 请求的 HttpContext

当请求终止时,该请求的同步上下文也随之终止。现在,当异步数据库访问完成时,它会尝试使用在 await 之前捕获的 SynchronizationContext 来运行 await 之后的代码(其中包括处理 SQL 连接的代码),但由于请求已终止,它无法再找到它。

在这种情况下,您可以做的是让 await 之后的代码不依赖于当前 ASP.NET 请求的 SynchronizationContext,而是在 Thread-pool 线程上运行。您可以通过 ConfigureAwait 执行此操作像这样的方法:

private async Task<T> CallDatabaseAsync<T>(Func<SqlConnection, Task<T>> execAsync)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
return await execAsync(connection).ConfigureAwait(false);
}
}

关于c# - Using block 中的异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37357828/

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