C# WinForm 应用程序 UI 在长时间运行期间挂起

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1216791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 13:46:29  来源:igfitidea点击:

WinForm Application UI Hangs during Long-Running Operation

c#winformsmultithreading

提问by shahjapan

I have a windows forms application on which I need to use a for loop having a large number of Remote Calls around 2000 - 3000 calls,

我有一个 Windows 窗体应用程序,我需要在该应用程序上使用一个 for 循环,该循环具有大约 2000 - 3000 个调用的大量远程调用,

and while executing the for loop, I loose my control on form and form controls, as it becomes a large process and some time it shows "Not Responding" but if I wait for a long it comes back again, I think I need to use some threading model for that, is there any idea, how can I proceed to solve the issue?

并且在执行 for 循环时,我失去了对表单和表单控件的控制,因为它变成了一个大进程,有时它显示“无响应”,但如果我等了很长时间它又回来了,我想我需要使用一些线程模型,有什么想法,我该如何解决这个问题?

采纳答案by Simon P Stevens

You need to perform the long running operation on a background thread.

您需要在后台线程上执行长时间运行的操作。

There are several ways of doing this.

有几种方法可以做到这一点。

  1. You can queue the method call for execution on a thread pool thread (See here):

    ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
    

    In .NET 4.0 you can use the TaskFactory:

    Task.Factory.StartNew(() => YourMethod());
    

    And in .NET 4.5 and later, you can (and should, rather than TaskFactory.StartNew()) use Task.Run():

    Task.Run(() => YourMethod());
    
  2. You could use a BackgroundWorkerfor more control over the method if you need things like progress updates or notification when it is finished. Drag the a BackgroundWorker control onto your form and attach your method to the dowork event. Then just start the worker when you want to run your method. You can of course create the BackgroundWorker manually from code, just remember that it needs disposing of when you are finished.

  3. Create a totally new thread for your work to happen on. This is the most complex and isn't necessary unless you need really fine grained control over the thread. See the MSDN page on the Threadclass if you want to learn about this.

  1. 您可以将方法调用排队以在线程池线程上执行(请参阅此处):

    ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
    

    在 .NET 4.0 中,您可以使用TaskFactory

    Task.Factory.StartNew(() => YourMethod());
    

    在 .NET 4.5 及更高版本中,您可以(并且应该,而不是TaskFactory.StartNew())使用Task.Run()

    Task.Run(() => YourMethod());
    
  2. 如果您需要诸如进度更新或完成时的通知之类的内容,您可以使用BackgroundWorker对方法进行更多控制。将 BackgroundWorker 控件拖到您的表单上,并将您的方法附加到 dowork 事件。然后在您想要运行您的方法时启动工作程序。您当然可以从代码中手动创建 BackgroundWorker,但请记住,完成后需要对其进行处理。

  3. 为您的工作创建一个全新的线程。这是最复杂的,除非您需要对线程进行真正细粒度的控制,否则这不是必需的。如果您想了解这一点,请参阅Thread类的 MSDN 页面。

Remember that with anything threaded, you cannotupdate the GUI, or change any GUI controls from a background thread. If you want to do anything on the GUI you have to use Invoke (and InvokeRequired) to trigger the method back on the GUI thread. See here.

请记住,任何线程都不能更新 GUI,也不能从后台线程更改任何 GUI 控件。如果您想在 GUI 上执行任何操作,您必须使用 Invoke(和 InvokeRequired)在 GUI 线程上触发该方法。见这里

回答by Reza Sadr

Obviously, you need to use background threads. I suggest you read this free e-book.

显然,您需要使用后台线程。我建议你阅读这本免费的电子书

回答by VOX

    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.
    }

use MethodInvoker is the easiest way.

使用 MethodInvoker 是最简单的方法。