c# - 如何在 ASP.NET webservice 中执行 SQL 事务异步

标签 c# asp.net sql asynchronous

我的网络服务有很多连接。 我使用了这段代码:

IAsyncResult result = sqlCommand.BeginExecuteNonQuery();
while (!result.IsCompleted)
{
   System.Threading.Thread.Sleep(500);
}
sqlCommand.EndExecuteNonQuery(result);

我认为这不是最佳方法,因为我调用了 Sleep()。 附言。此方法会降低 WebService 和服务器的性能

更新 2: 我尝试更多地描述我的代码: 我有 WebClient 和 2 个事件(ProgressChangedDownloadCompleted)

[WebMethod]
public void DonwloadFromRemoteServer(string uniqueId, string url)
{
    if (!Directory.Exists(uniqueId))
        Directory.CreateDirectory(uniqueId);

    WebClient wc = new WebClient();

    wc.DownloadProgressChanged += (sender, args) => wc_DownloadProgressChanged(sender, args, uniqueId, Path.GetFileName(url));

    wc.DownloadFileCompleted += (sender, args) => wc_DownloadFileCompleted(sender, args, uniqueId, Path.GetFileName(url));
    wc.DownloadFileAsync(new Uri(url), String.Format("{0}\\{1}", uniqueId, Path.GetFileName(url)));
}

void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e, string uniqueId, string fileName)
{
    SqlConnection connection = new SqlConnection("Data Source=.\\SQLSERVER;Initial Catalog=XRingtoneDB;Integrated Security=True;Asynchronous Processing=true");
    connection.Open();
    SqlCommand sqlCommand = new SqlCommand();
    sqlCommand.Connection = connection;
    sqlCommand.CommandText = String.Format("IF NOT EXISTS(SELECT uniqueId FROM downloads WHERE uniqueID = '{0}') " +
                                       "INSERT INTO downloads VALUES ('{0}', '{1}', '{2}') " +
                                       "IF EXISTS(SELECT uniqueId FROM downloads WHERE uniqueID = '{0}') " +
                                       "Update downloads " +
                                       "set progress='{2}' " +
                                       "where uniqueId='{0}' ", uniqueId, fileName, e.BytesReceived);

    AsyncCallback callback = ((result) =>
    {
        sqlCommand.EndExecuteNonQuery(result);
        connection.Close();
    });

    sqlCommand.BeginExecuteNonQuery(callback, sqlCommand);
}

void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e, string uniqueId, string fileName)
{
    SqlConnection connection = new SqlConnection("Data Source=.\\SQLSERVER;Initial Catalog=XRingtoneDB;Integrated Security=True;Asynchronous Processing=true");
    connection.Open();
    SqlCommand sqlCommand = new SqlCommand();
    sqlCommand.Connection = connection;

    sqlCommand.CommandText = String.Format("update downloads " +
                                                "set progress='Completed' " +
                                                "where uniqueId='{0}' and fileName='{1}'", uniqueId, fileName);

    AsyncCallback callback = ((result) =>
    {
        sqlCommand.EndExecuteNonQuery(result);
        sqlCommand.Connection.Close();
    });
    sqlCommand.BeginExecuteNonQuery(callback, sqlCommand);
}

ProgressChanged 工作正常,但 DownloadCompleted 仅在 Debug模式下工作。 我认为发生这种情况是因为我需要超时或在这些调用之间等待一些时间。

更新 3: 有时我在执行下载后在数据库中有两个相同的行! 困惑 我是否需要关闭所有连接?

最佳答案

你可以使用 AsyncCallback 而不是 Sleep()

AsyncCallback callback = new AsyncCallback(HandleCallback);
sqlcommand.BeginExecuteNonQuery(callback, sqlcommand);

使用回调处理异步状态。

private void HandleCallback(IAsyncResult result)
{
  SqlCommand command = (SqlCommand)result.AsyncState;
  command.EndExecuteNonQuery(result);
  ....
}

更新 2

代码总体上不错,但是,您是否允许在一个唯一 ID 中下载多个文件?如果您正在下载具有相同唯一 ID 的不同文件,它可能会更新报告不完整进度的下载表。

不确定您的意思 DownloadCompleted 仅在 Debug模式下工作,但是您可以在 WebMethod 中使用私有(private)变量来控制流程。说到这一点,由于您使用数据库来报告状态已更改但没有插入大量数据,因此您应该考虑使用同步查询,以便更好地存档结果。

关于c# - 如何在 ASP.NET webservice 中执行 SQL 事务异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8394750/

相关文章:

sql - 为什么在此查询中 LIMIT 2 比 LIMIT 1 长几个数量级?

sql - 大型数据库的优化技术

c# - 公共(public)领域可以吗?

c# - WebAPI - 对象数组在服务器端未正确反序列化

asp.net - web.config urlmapping

php - 多个数据库用户同时更新

c# - 使用应用内购买在商店中购买商品

c# - 发送 IP 数据包

c# - ASP.NET MVC 能否防止 Open Redirect 安全问题

javascript - jsonp : Uncaught SyntaxError: Unexpected token <