gpt4 book ai didi

c# - 通过 web 服务异步执行长时间运行的存储过程

转载 作者:行者123 更新时间:2023-11-30 16:49:46 27 4
gpt4 key购买 nike

我有一个 SQL Server 存储过程负责处理大量数据,运行时间从 15 秒到几分钟不等。我正在尝试使用由来自桌面 UI 客户端的请求调用的异步 MVC 操作异步执行它。我似乎完全按照 .NET 异步书籍和教程教授的方式进行所有操作,但存储过程似乎在启动后不久就中止了。

启动时,存储过程会向状态表添加一条记录以指示正在进行的作业。成功完成后,存储过程使用成功标志更新状态记录,任何错误都由 TRY-CATCH block 处理,该 block 使用错误标志更新状态记录。

这已经在 SQL Server Management Studio 中进行了全面测试,因此我确信存储过程不会悄无声息地爆炸。然而,当存储过程通过异步调用执行时(见下文),作业记录被插入到状态表中,但它没有得到更新,这意味着存储过程永远不会结束并在运行中终止,可能是由于关闭了数据库连接。

存储过程调用包装在这个异步存储库方法中:

    public async Task ProcessCatalogUpdateAsync(Guid updateID)
{
try
{
using (var cmd = new SqlCommand("ProcessCatalogUpdate", new SqlConnection(_connectionString)))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
cmd.Parameters.Add("@UpdateID", SqlDbType.UniqueIdentifier).Value = updateID;

cmd.Connection.Open();

await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
}
catch (Exception ex)
{
var message = String.Format("Error processing catalog update ID={0}", updateID);
throw new DataException(message, ex);
}
}

Controller Action 看起来像这样:

    public async Task UpdateCatalog(string updateID)
{
var uid = Guid.Empty; // breakpoint here
if (!Guid.TryParse(updateID, out uid))
throw new Exception("Bad UpdateID in request!");

await _repository.ProcessCatalogUpdateAsync(uid);

System.Diagnostics.Trace.WriteLine("Catalog update completed"); // breakpoint here
}

我构建了一个简单的 HTML 页面形式的测试工具,它使用 jQuery 异步调用操作,如下所示:

    var requestURL = "/catalog/updateCatalog?updateID=" + $("#updateID").val();

$.ajax({
url: requestURL,
type: "GET",
error: function (xhr, status, errorText) {
alert("Error: " + errorText); // breakpoint here
},
success: function () {
alert("Call returned!"); // breakpoint here
}
});

我在 JavaScript 中的两个警报处以及我的 Controller 操作方法的开头都放置了断点,以确认该操作已实际执行。在 await 调用存储库方法之后,我还在 System.Diagnostics 行设置了一个断点,以便在方法返回时捕获(尽管在调试 session 中它可能毫无意义)因为线程上下文可能不同)。

是这样的:

  • UpdateCatalog Action 开头的断点被命中
  • 存储过程向状态表中插入一个新行
  • success JavaScript 处理程序永远不会触发
  • 状态表永远不会用成功或错误标志更新
  • 永远不会命中 System.Diagnostics 处的断点

我做错了什么?


更新

事实证明,存储过程代码本身存在问题,最终执行的操作需要 20 多分钟才能完成。我现在重写了它,使其工作速度提高了几个数量级。但是,异步的东西仍然没有按我预期的方式工作。 jQuery AJAX success 事件仅在 Controller 操作方法在 await 行之后恢复时触发,而不是立即触发。

我应该如何更改我的 Controller 操作方法以真正的“即发即弃”方式执行?

最佳答案

await 不会启动工作。它等待已经在运行的工作。因此,await 不是启动即发即弃的方法。

改变

await _repository.ProcessCatalogUpdateAsync(uid);

_repository.ProcessCatalogUpdateAsync(uid);

并将诊断日志移到 ProcessCatalogUpdateAsync 中(或移到包装器方法中)。现在这就是火了,不管了。

“即发即弃”有其危险。工作可能会在没有通知的情况下丢失,或者如果启动得太快,并发 fire and forget 工作可能会累积并使服务过载。

关于c# - 通过 web 服务异步执行长时间运行的存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35972863/

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