【发布时间】:2016-09-14 01:48:29
【问题描述】:
我们有一个遗留的 VB6 应用程序,它使用一个用 C# (.NET 4.5) 编写的 ASMX Web 服务,该服务又使用一个库 (C#/.NET 4.5) 来执行一些业务逻辑。其中一个库方法触发了一个长时间运行的数据库存储过程,在该过程结束时,我们需要启动另一个使用存储过程生成的数据的进程。因为其中一个要求是调用webservice后控件必须立即返回VB6客户端,所以库方法为async,以Action回调为参数,webservice将回调定义为匿名方法,并没有t await 库方法调用的结果。
在高层次上是这样的:
使用系统; 使用 System.Data.SqlClient; 使用 System.Threading.Tasks; 使用 System.Web.Services; 命名空间示例 { [WebService(Namespace = "urn:Services")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 公共类 MyWebService { [网络方法] 公共字符串请求(字符串请求) { // 第一步:调用库方法生成数据 var lib = new MyLibrary(); lib.GenerateDataAsync(() => { // 第 2 步:启动一个使用第 1 步中创建的数据的进程 }); 返回“某种响应”; } } 公共课 MyLibrary { 公共异步任务 GenerateDataAsync(Action onDoneCallback) { 尝试 { 使用 (var cmd = new SqlCommand("MyStoredProc", new SqlConnection("my DB connection string"))) { cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.CommandTimeout = 0; cmd.Connection.Open(); // 异步调用存储过程。 等待 cmd.ExecuteNonQueryAsync().ConfigureAwait(false); // 如果提供了回调,则调用它。 如果(onDoneCallback != null) onDoneCallback.Invoke(); } } 捕捉(例外前) { // 处理错误... } } } }以上内容在本地测试中有效,但是当代码部署为 Web 服务时,即使 Step 1 存储过程完成并生成数据,Step 2 也永远不会执行.
知道我们做错了什么吗?
【问题讨论】:
-
您本地计算机的防火墙可能会阻止传入连接...
-
顺便说一句,我猜第 1 步正在调用
lib.GenerateDataAsync(说GenerateData,未显示)。我认为问题在于 asmx 请求已完成执行并且“出门在外”,并且“无处执行”回调。你试过等待那个电话吗? -
查看您的请求实现。如果您使用异步,则必须在整个管道中使用它以获得最一致的解决方案。
-
@MarkLarter,感谢您注意到我的错字,我已修复它。在 Web 服务中等待调用会破坏运行存储过程的整个“即发即弃”的方法。我同意可能的原因是调用
GenerateDataAsync的线程在调用完成时被 IIS 回收,因此没有执行回调的上下文。我只是希望“去过那里,做过那个”的人可以提出解决方法。 -
@CaspianCanuck 绝对是 BTDT,但不是自 .NET 2.0 (BeginAsync...) 以来。等待仍应释放 IIS 工作线程以处理其他 Web 请求,因此您不会阻塞您的请求管道。不知道您还需要通过“即发即弃”完成什么,所以诚然,这可能不足以满足您的需求。
标签: c# asp.net web-services asynchronous async-await