Bri*_*tle 4 c# multithreading compact-framework winforms
我正在开发一个应用程序,它可以从外部服务器上获取并安装一堆更新,并且需要一些线程帮助.用户遵循以下过程:
进度条更新很好,但MessageBox未从屏幕上完全清除,因为更新循环在用户单击是后立即启动(请参见下面的屏幕截图).
码
// Button clicked event handler code...
DialogResult dlgRes = MessageBox.Show(
string.Format("There are {0} updates available.\n\nInstall these now?",
um2.Updates.Count), "Updates Available",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2
);
if (dlgRes == DialogResult.Yes)
{
ProcessAllUpdates(um2);
}
// Processes a bunch of items in a loop
private void ProcessAllUpdates(UpdateManager2 um2)
{
for (int i = 0; i < um2.Updates.Count; i++)
{
Update2 update = um2.Updates[i];
ProcessSingleUpdate(update);
int percentComplete = Utilities.CalculatePercentCompleted(i, um2.Updates.Count);
UpdateOverallProgress(percentComplete);
}
}
// Process a single update with IAsyncResult
private void ProcessSingleUpdate(Update2 update)
{
update.Action.OnStart += Action_OnStart;
update.Action.OnProgress += Action_OnProgress;
update.Action.OnCompletion += Action_OnCompletion;
//synchronous
//update.Action.Run();
// async
IAsyncResult ar = this.BeginInvoke((MethodInvoker)delegate() { update.Action.Run(); });
}
Run Code Online (Sandbox Code Playgroud)
截图
您的UI未更新,因为所有工作都在用户界面线程中进行.您致电:
this.BeginInvoke((MethodInvoker)delegate() {update.Action.Run(); })
Run Code Online (Sandbox Code Playgroud)
是说在创建"this"(你的表单)的线程上调用update.Action.Run(),这是用户界面线程.
Application.DoEvents()
Run Code Online (Sandbox Code Playgroud)
确实会给UI线程重绘屏幕的机会,但我很想创建新的委托,并调用BeginInvoke.
这将在从线程池分配的单独线程上执行update.Action.Run()函数.然后,您可以继续检查IAsyncResult,直到更新完成,在每次检查后查询更新对象的进度(因为您不能让其他线程更新进度条/ UI),然后调用Application.DoEvents().
你也应该在之后调用EndInvoke(),否则你可能最终泄漏资源
我也很想在进度对话框上放置一个取消按钮,并添加超时,否则如果更新卡住(或需要太长时间),那么您的应用程序将永久锁定.