我有很多连接到它的webservice。我使用了以下代码:
IAsyncResult result = sqlCommand.BeginExecuteNonQuery();
while (!result.IsCompleted)
{
System.Threading.Thread.Sleep(500);
}
sqlCommand.EndExecuteNonQuery(result);
我认为这不是一个最好的方法,因为我调用Sleep()
。PS.这种方法会降低WebService和服务器的性能
更新2:我试着更多地描述我的代码:我有WebClient和2事件(ProgressChanged
和DownloadCompleted
)
[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
只在调试模式下工作。我认为这是因为我需要在调用之间进行超时或等待。
Update3: 有时我有两个相同的行DB后执行下载!混淆我需要关闭所有的连接吗?
你可以用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
只在调试模式下工作,但是你可以在你的WebMethod中使用一个私有变量来控制流。说到这一点,因为您使用DB来报告状态变化,但不插入大量数据,您应该考虑使用同步查询,以便它可以更好地存档结果。
你应该调用BeginExecuteNonQuery的重载,它接受一个回调,并在回调中结束查询。
如果您有额外的代码需要在数据库执行完成后执行,那么这些代码需要在回调中启动。
例如,如果您当前有:
sqlCommand.BeginExecuteNonQuery(callback, sqlCommand);
DoSomeAdditionalWorkNow();
DoSomeAdditionalWorkNow
不会等到查询完成,如果它依赖于命令中更新的数据,您将遇到问题。
AsyncCallback callback = ((result) =>
{
sqlCommand.EndExecuteNonQuery(result);
connection.Close();
DoSomeAdditionalWorkNow();
});
sqlCommand.BeginExecuteNonQuery(callback, sqlCommand);
然而我认为你的编程生活过于复杂了。您正在执行的查询不会长时间运行,您可以使用同步版本执行它们:
sqlCommand.ExecuteNonQuery();