ThreadPool.QueueUserWorkItem与BeginExecuteNonQuery

时间:2014-06-09 09:56:24

标签: c# asp.net sql-server threadpool

我在使用简单的插入方法时遇到问题,因为数据库表上的计划清理任务偶尔会超时。此任务每十分钟运行一次,在执行期间,由于“等待操作超时”,我的代码通常会在事件日志中记录错误。

我正在考虑的一个解决方案是使代码调用存储过程异步,为了做到这一点,我首先开始查看BeginExecuteNonQuery方法。

我尝试过使用BeginExecuteNonQuery方法,但发现它根本不会插入行。我使用的代码如下:

SqlConnection conn = daService.CreateSqlConnection(dataSupport.DBConnString);
SqlCommand command = daService.CreateSqlCommand("StoredProc");

try {
    command.Connection = conn;

    command.Parameters.AddWithValue("page", page);
    command.Parameters.AddWithValue("Customer", customerId);

    conn.Open();

    command.BeginExecuteNonQuery(delegate(IAsyncResult ar) {
        SqlCommand c = (SqlCommand)ar.AsyncState;

        c.EndExecuteNonQuery(ar);
        c.Connection.Close();
    }, command);

} catch (Exception ex) {
     LogService.WriteExceptionEntry(ex, EventLogEntryType.Error);
} finally {
     command.Connection.Close();
     command.Dispose();
     conn.Dispose();
}

显然,我不期待即时插入,但我希望在低使用率开发数据库上五分钟后插入它。

I've now switched to the following code,它执行插入操作:

System.Threading.ThreadPool.QueueUserWorkItem(delegate {
      using (SqlConnection conn = daService.CreateSqlConnection( dataSupport.DBConnString)) {
         using (SqlCommand command = daService.CreateSqlCommand("StoredProcedure")) {
             command.Connection = conn;

             command.Parameters.AddWithValue("page", page);
             command.Parameters.AddWithValue("customer", customerId);

             conn.Open();
             command.ExecuteNonQuery();
         }
      }
  });

我有几个问题,其中一些是假设:

由于我的insert方法的签名是无效的,我假设调用它的代码不等待响应。这是对的吗?

为什么BeginExecuteNonQuery不运行存储过程?我的代码错了吗?

最重要的是,如果我使用QueueUserWorkItem(或表现良好的BeginExecuteNonQuery),我认为这会产生预期效果吗?也就是说,在计划任务运行时尝试运行存储过程会在任务完成后看到代码执行,而不是当前超时?

修改

这是我现在用来回应我收到的评论和答案的版本。

SqlConnection conn = daService.CreateSqlConnection(
              string.Concat("Asynchronous Processing=True;",
              dataSupport.DBConnString));
SqlCommand command = daService.CreateSqlCommand("StoredProc");

command.Connection = conn;

command.Parameters.AddWithValue("page", page);
command.Parameters.AddWithValue("customer", customerId);

conn.Open();
command.BeginExecuteNonQuery(delegate(IAsyncResult ar) {
      SqlCommand c = (SqlCommand)ar.AsyncState;

      try {
          c.EndExecuteNonQuery(ar);
      } catch (Exception ex) {
           LogService.WriteExceptionEntry(ex, EventLogEntryType.Error);
      } finally {
          c.Connection.Close();
          c.Dispose();
          conn.Dispose();
      }

 }, command);

1 个答案:

答案 0 :(得分:2)

  

为什么BeginExecuteNonQuery没有运行存储的原因   程序?我的代码错了吗?

可能您没有在连接字符串中添加Asynchronous Processing=True

此外 - 可能存在这样的情况:当sql的响应准备就绪时 - asp.net响应已经发送。

这就是你需要使用的原因:Page.RegisterASyncTask(+ AsyncTimeout)

(如果你使用webform异步页面,你应该在页面指令中添加:Async="True"

P.S。这一行:

System.Threading.ThreadPool.QueueUserWorkItem在asp.net应用程序中是危险的。你应该注意还没有发送回应。