WinForm应用程序UI在长时间运行期间挂起
我有一个Windows窗体应用程序,我需要使用for循环有大量的远程调用2000 – 3000调用,
在执行for循环的时候,我放弃了对form和form控件的控制,因为它变成了一个很大的进程,有时它显示“Not Responding”,但是如果等待很长时间,它会再次返回,我想我需要使用有一些线程模型,有什么想法,我怎么才能着手解决这个问题?
您需要在后台线程上执行长时间运行的操作。
有几种方法可以做到这一点。
-
您可以在线程池线程上对方法调用进行排队(请参阅此处 ):
ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
或者在.NET 4.0中,您可以使用TaskFactory :
Task.Factory.StartNew(() => YourMethod());
-
如果您需要诸如进度更新或通知完成时的通知,则可以使用BackgroundWorker来更多地控制该方法。 将一个BackgroundWorker控件拖到您的表单上,并将您的方法附加到dowork事件。 然后,当你想运行你的方法时,只需启动worker。 您当然可以从代码手动创buildBackgroundWorker,只要记住它需要在完成时处置掉。
-
为您的工作创build一个全新的线程。 这是最复杂的,没有必要,除非你需要对线程进行细粒度的控制。 如果你想了解这个,请参阅Thread类的MSDN页面。
请记住,对于线程化的任何东西,您都无法更新GUI, 也无法从后台线程更改任何GUI控件。 如果要在GUI上执行任何操作,则必须使用Invoke(和InvokeRequired)在GUI线程上触发该方法。 看到这里 。
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是最简单的方法。
显然,你需要使用后台线程。 我build议你阅读这个免费的电子书 。
没有线程需要。 使用Application.DoEvents(); //repaint or respond to msg
Application.DoEvents(); //repaint or respond to msg
例如:
foreach (DirectoryInfo subDir in dirInfo.EnumerateDirectories()) { count = count + 1; listBoxControl4.Items.Add(count.ToString() + ":" + subDir.FullName); Application.DoEvents(); //allow repaint to see status ProduceListing(subDir, " "); }
这将recursion通过所有文件夹并将名称写入列表框。 这可能需要很长时间。 使用DoEvents(),它将显示每个循环的进度。 基本上,这个调用允许这个线程上的窗口更新windows msg循环中的任何东西。 一定要注意无意的recursion,因为即使你的第一个没有完成,再次点击表单上的任何控件。 这很好。 (这是旧的Delphi Application.ProcessMessages()调用的副本。您可以search,看看它为什么工作,以及要注意什么。