WinForm 应用程序 UI 在长时间运行期间挂起
Posted
技术标签:
【中文标题】WinForm 应用程序 UI 在长时间运行期间挂起【英文标题】:WinForm Application UI Hangs during Long-Running Operation 【发布时间】:2019-02-10 17:35:43 【问题描述】:我有一个 Windows 窗体应用程序 我需要使用一个 for 循环,在 2000 到 3000 左右的电话中进行大量远程调用,
在执行 for 循环时,我失去了对表单和表单控件的控制,因为它变成了一个大进程,并且有时它显示“无响应”但如果我等待很长时间它又回来了,我想我需要为此使用一些线程模型,有什么想法,我该如何继续解决这个问题?
【问题讨论】:
将Application.DoEvents()
放入循环中。
@i486 - 永远不要打电话给DoEvents()
。在代码中引入难以解决的错误是一种邪恶的方式。
【参考方案1】:
您需要在后台线程上执行长时间运行的操作。
有几种方法可以做到这一点。
您可以将方法调用排队等待在线程池线程上执行(请参阅here):
ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
在 .NET 4.0 中,您可以使用 TaskFactory:
Task.Factory.StartNew(() => YourMethod());
在 .NET 4.5 及更高版本中,您可以(并且应该,而不是 TaskFactory.StartNew()
)使用 Task.Run()
:
Task.Run(() => YourMethod());
如果您需要进度更新或完成时的通知等内容,您可以使用BackgroundWorker 来更好地控制该方法。将 BackgroundWorker 控件拖到表单上,并将您的方法附加到 dowork 事件。然后在您想运行您的方法时启动工作程序。您当然可以从代码中手动创建 BackgroundWorker,只需记住完成后需要处理它。
为您的工作创建一个全新的线程。这是最复杂的并且没有必要,除非您需要对线程进行真正细粒度的控制。如果您想了解这一点,请参阅 Thread 课程上的 MSDN 页面。
请记住,对于任何线程,您无法更新 GUI,或从后台线程更改任何 GUI 控件。如果您想在 GUI 上做任何事情,您必须使用 Invoke(和 InvokeRequired)在 GUI 线程上触发该方法。见here。
【讨论】:
【参考方案2】: private voidForm_Load(object sender, EventArgs e)
MethodInvoker mk = delegate
//your job
;
mk.BeginInvoke(callbackfunction, null);
private void callbackfunction(IAsyncResult res)
// it will be called when your job finishes.
使用 MethodInvoker 是最简单的方法。
【讨论】:
【参考方案3】:显然,您需要使用后台线程。我建议你阅读this free e-book。
【讨论】:
以上是关于WinForm 应用程序 UI 在长时间运行期间挂起的主要内容,如果未能解决你的问题,请参考以下文章
在应用程序关闭期间正确关闭一个可能运行很长时间循环的线程[重复]
使用 ReSharper,如何在长时间运行的单元测试期间显示调试输出?