【问题标题】:Executing a stored procedure within a function and not waiting for the return在函数内执行存储过程而不等待返回
【发布时间】:2013-05-22 16:40:19
【问题描述】:

我知道在某些地方我可能忽略了某些东西,但我正在尝试修复一个我没有开发且通常不维护的应用程序,所以如果我犯了直截了当的错误,请提前原谅我。

目前这个网络应用程序存在一个问题,在执行某个函数时会导致超时,我已经追踪到一件事,它正在执行一个存储过程并期望该存储过程返回 # of受影响的行,这一切都很好。但是,此存储过程至少运行 50 秒并导致超时。另外,我不希望 UI 在发生这种情况时挂起 50 秒,它只是根据更改的信息更新数据库中的一些状态字段,它返回的内容对最终用户没有用,所以它只是需要触发和忘记,以便用户可以继续使用应用程序。

我已经尝试过创建任务和创建线程,但由于某种原因,该函数坚持等待它完成。

这是调用存储过程的函数:

 public static void UpdateComputerStatusByApplicationID(int ApplicationID)
{
    using (SqlConnection Conn = new SqlConnection(GlobalMethods.CONNECTION_STRING))
    {
        SqlCommand Cmd = new SqlCommand("UpdateComputerStatusByApplicationId", Conn);
        Cmd.CommandType = CommandType.StoredProcedure;
        Cmd.Parameters.Add("@applicationid", SqlDbType.Int).Value = ApplicationID;

        Conn.Open();
        Cmd.ExecuteNonQuery();
        Conn.Close();
    }
}

异常来自 Cmd.ExecuteNonQuery();这是一个超时异常。

这是我将其作为函数中的任务调用的地方:

public void UpdateApplication(a_Applications newApplication, XPToWin7 xpToWin7)
    {
        try
        {
            var orginalApplication = GetApplication(newApplication.AutoNumber);
            ObjectContext.ApplyCurrentValues(orginalApplication.EntityKey.EntitySetName, newApplication);

            if (xpToWin7 != null)
            {
                UnlinkXPAppWithWin7App(orginalApplication.AutoNumber);
                LinkXPAppWithWin7App(orginalApplication.AutoNumber, xpToWin7);
            }

            Task UpdateComputerStatus = Task.Factory.StartNew(() =>
            {
                DAL.UpdateComputerStatusByApplicationID(orginalApplication.AutoNumber);
            }, TaskCreationOptions.LongRunning);

            SaveChanges();
        }
        catch (Exception ex)
        {
            throw new Exception("Exception when updating the application" + ex.Message, ex);
        }
    }

我不确定我哪里出错了,或者为什么它没有按预期工作,但是当这个函数被调用时,它只是挂在 UI 中,直到它抛出一个来自 cmd.ExecuteNonQuery( ); .

任何帮助或建议将不胜感激!

【问题讨论】:

  • 开始将cmd.CommandTimeout属性改为更长的值,默认为30秒。这应该解决超时异常,但不是 UI 挂起
  • 50 秒对于存储过程来说是很长的时间 - 请您发布存储过程,也许它使用了可以删除的游标,或者可能缺少索引
  • 另外,UI 问题可以通过在不同线程上进行 UI 和 Data 操作来解决。考虑使用 BackgroundWorker 并异步调用更新方法。
  • 你在使用 SQL Server 吗?
  • 您是否尝试过在应用程序之外运行该过程以查看它是否也需要 50 秒才能完成?

标签: c# asp.net sql stored-procedures


【解决方案1】:

从客户端异步调用存储过程可能会非常痛苦 - 您必须考虑多个线程、BeginXXX 和 EndXXX 方法、使用回调并且应用程序必须在完成之前保持活动状态 - 否则可能会发生回滚。是的,有可能 - 看看这个答案:Asynchronous call of a SQL Server stored procedure in C#

可能有一种更简单的方法——为什么不让存储过程异步呢?使用 Service Broker,您可以创建一个简单的队列来激活存储过程。调用存储过程不必等待响应。它只是创建一个传递请求详细信息的新对话并立即返回。激活的存储过程负责完成所有可能需要几秒钟、几分钟或几小时的繁重工作——但这​​对 UI 来说并不重要,因为它不会坐在那里等待响应。即使您的 UI 关闭,异步存储过程也会一直运行直到完成。

http://rusanu.com/2009/08/05/asynchronous-procedure-execution/

【讨论】:

  • 嘿,克里斯,所以我尝试了几个选项,包括从存储过程调用作业,这让我比我更进一步,因为 UI 不再挂起,但是一旦你介绍了多个用户您会遇到错误,因为作业无法在多个实例中运行。我认为服务代理是解决此问题的方法,我想知道您是否可以指出我可以做类似事情的解决方案示例?我不熟悉使用 Service Broker,因为我主要在 SharePoint 领域工作,但最近开始为我们的应用程序团队做一些工作。
  • @BAllan - 添加了我的答案的链接。
猜你喜欢
  • 1970-01-01
  • 2020-01-14
  • 2018-06-21
  • 2019-09-24
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
  • 2017-12-22
  • 1970-01-01
相关资源
最近更新 更多