【发布时间】:2014-02-14 17:56:14
【问题描述】:
我正在使用后台工作人员进行耗时的操作(将一些数据上传到服务器并从服务器下载一些数据)。所有服务器通信都是通过 http 请求(GET、POST、PUT、Delete),我使用的代码是
private void btnSync_Click(object sender, RoutedEventArgs e)
{
btnSync.IsEnabled = false;
BackgroundWorker syncWorker = new BackgroundWorker();
syncWorker.WorkerReportsProgress = true;
syncWorker.WorkerSupportsCancellation = true;
syncWorker.DoWork+=new DoWorkEventHandler(syncWorker_DoWork);
syncWorker.ProgressChanged+=new ProgressChangedEventHandler(syncWorker_ProgressChanged);
syncWorker.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(syncWorker_RunWorkerCompleted);
syncWorker.RunWorkerAsync();
}
private void syncWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker target = (BackgroundWorker)sender;
foreach (...........) // a loop to do some set of actions on some objects
{
target.ReportProgress(1, obj);
target.ReportProgress(2, obj);
target.ReportProgress(3, obj);
}
target.ReportProgress(4);
}
private void syncWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 1)
{
string id= e.UserState.ToString();
mySyncHelper.DOGETFROMServer(id); //Issue a GET request and read and process resposne (deserialize json data and insert to local DB)
}
if (e.ProgressPercentage == 2)
{
string id= e.UserState.ToString();
mySyncHelper.DOGETFROMServer(id);//Issue a GET request and read and process resposne(deserialize json data and insert to local DB)
}
if (e.ProgressPercentage == 3)
{
string id= e.UserState.ToString();
mySyncHelper.DOGETFROMServer(id);//Issue a GET request and read and process resposne (deserialize json data and insert/Update response data to local DB)
}
if (e.ProgressPercentage ==4)
{
mySyncHelper.DOPOSTToServer();//Issue a POST request and read and process resposne (deserialize json data and insert/Update response data to local DB)
mySyncHelper.DOPUTToServer();
mySyncHelper.DODELETEToServer();
}
}
private void syncWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
txtSyncStatus.Visibility = Visibility.Visible;
txtSyncStatus.Text = string.Concat(DbookLanguage.message_error, Environment.NewLine , e.Error.Message.ToString());
}
else
{
btnSync.IsEnabled = true;
txtSyncStatus.Text = "";
}
}
我面临的问题是@某些阶段应用程序正在等待一段时间以获取对 http 请求的响应,并且在此状态下,整个应用程序进入冻结状态。我用于从服务器获取响应的代码是 var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); 在这种状态下,应用程序没有响应。
如何防止这种情况发生?是否有任何其他好方法可以进行一系列 Http 请求并使应用程序 UI 具有交互性
【问题讨论】:
-
BackgroundWorker.ProgressChanged和BackgroundWorker.RunWorkerCompleted的重点在于它们都运行在启动工作的线程(UI 线程)上。它编组回 UI 线程,以便您可以更新屏幕。但是,您正在BackgroundWorker.ProgressChanged上执行 Blocking IO,这在 UX 中是一个很大的禁忌。您绝对应该查看.net 4.5asyncawait。实现非阻塞 UI 要容易得多。 -
或者,您可以将每个
mySyncHelper.DOXXXTToServer()放入自己的BackgroundWorker。 -
我仅限于 .net 4。在我的移动应用程序(.net - 4.5)中,我也在使用异步等待模式。那么我该如何克服这种情况。我想在这些操作发生时使 UI 具有交互性
-
天哪……我才意识到你在做什么。您正在使用 ThreadPool 线程将工作安排到您的 UI 线程上。您已经反转了后台工作线程模式。如果您在 UI 线程上循环执行所有操作,您实际上会获得性能,并阻塞 稍微 更短的时间。
-
我刚刚意识到代码中的错误之处,非常感谢您能解决这个问题。我稍微改变一下这样的顺序(pastebin.com/q4e0B4R1),可以吗?
标签: c# c#-4.0 backgroundworker