VB调用SQL存储过程异步执行问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VB调用SQL存储过程异步执行问题相关的知识,希望对你有一定的参考价值。

VB调用SQL存储过程,并将结果输出到excel,存储过程的功能是将运算后的数据存入指定表,由于运算比较复杂,耗时较长,存储过程在SQL中显示正确结果,但是使用VB调用时存储过程时还没有执行完,VB就开始执行后面的程序了,导致只能输出部分结果(例如有SQL中有... VB调用SQL存储过程,并将结果输出到excel,存储过程的功能是将运算后的数据存入指定表,由于运算比较复杂,耗时较长,存储过程在SQL中显示正确结果,但是使用VB调用时存储过程时还没有执行完,VB就开始执行后面的程序了,导致只能输出部分结果(例如有SQL中有20列数据,但是只输出到excel11列),加入了事务也不行,显示超时,请问如何解决上面的问题哪 展开

参考技术A (下面是我在VB中使用过的方法,DELPHI中同样也能使用ADO异步操作访问SQL'adAsyncExecute指令异步操作这样你的应用程序就不用等待存储过程执行完毕后才

带有回调的 .NET 异步 Web 服务调用

【中文标题】带有回调的 .NET 异步 Web 服务调用【英文标题】:.NET async webservice call with a callback 【发布时间】: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 请求,因此您不会阻塞您的请求管道。不知道您还需要通过“即发即弃”完成什么,所以诚然,这可能不足以满足您的需求。 【参考方案1】:

让任务在 IIS 上运行很危险,应用程序域可能会在方法完成之前关闭,这很可能发生在您身上。如果您使用HostingEnvironment.QueueBackgroundWorkItem,您可以告诉 IIS 正在发生需要保持运行的工作。这将使应用程序域保持额外的 90 秒(默认情况下)

using System;
using System.Data.SqlClient;
using System.Threading.Tasks;
using System.Web.Services;

namespace Sample

    [WebService(Namespace = "urn:Services")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class MyWebService
    
        [WebMethod]
        public string Request(string request)
        
            // Step 1: Call the library method to generate data
            var lib = new MyLibrary();
            HostingEnvironment.QueueBackgroundWorkItem((token) =>
                lib.GenerateDataAsync(() =>
                
                    // Step 2: Kick off a process that consumes the data created in Step 1
                ));

            return "some kind of response";
        
    

    public class MyLibrary
    
        public async Task GenerateDataAsync(Action onDoneCallback)
        
            try
            
                using (var cmd = new SqlCommand("MyStoredProc", new SqlConnection("my DB connection string")))
                
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                    cmd.CommandTimeout = 0;
                    cmd.Connection.Open();

                    // Asynchronously call the stored procedure.
                    await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);

                    // Invoke the callback if it's provided.
                    if (onDoneCallback != null)
                        onDoneCallback();
                
            
            catch (Exception ex)
            
                // Handle errors...
            
        
    

如果您想要比额外 90 秒更可靠的东西,请参阅 Stephen Cleary 的文章“Fire and Forget on ASP.NET”了解其他选项。

【讨论】:

【参考方案2】:

我找到了一个解决我的问题的方法,它涉及到异步执行代码的旧式(开始/结束)方法:

    public void GenerateData(Action onDoneCallback)
    
        try
        
            var cmd = new SqlCommand("MyStoredProc", new SqlConnection("my DB connection string"));
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.CommandTimeout = 0;
            cmd.Connection.Open();

            cmd.BeginExecuteNonQuery(
                (IAsyncResult result) =>
                
                    cmd.EndExecuteNonQuery(result);
                    cmd.Dispose();

                    // Invoke the callback if it's provided, ignoring any errors it may throw.
                    var callback = result.AsyncState as Action;
                    if (callback != null)
                        callback.Invoke();
                ,
                onUpdateCompleted);
        
        catch (Exception ex)
        
            // Handle errors...
        
    

onUpdateCompleted 回调操作作为第二个参数传递给BeginExecuteNonQuery 方法,然后在AsyncCallback(第一个参数)中使用。在 VS 中进行调试和部署到 IIS 时,这都是一种魅力。

【讨论】:

以上是关于VB调用SQL存储过程异步执行问题的主要内容,如果未能解决你的问题,请参考以下文章

vb6中如何调用sql的储存过程?

在 VB.NET 中从 SQL Server 执行存储过程?

SQL Server 存储过程并在 VB.NET 中执行

sqlserver存储过程怎么调试

如何使用 VB.NET 配置 DataAdapter 以使用 Sql Server 存储过程执行 Select、Update、Insert 和 Delete 命令?

vs2005怎么调用sql语句,需要加啥头文件?