一个少年问题...
我意识到在Winforms应用程序中,长时间运行的代码应该在自己的线程中执行。如何实现这一点,例如按钮点击事件?
我想这样做是为了释放UI线程,以便我可以同时使用半透明模式对话框表单覆盖当前表单。我已经创建了模态对话框表单,其中有一个位于中心的整齐加载GIF,它可以完全独立于按钮点击事件。
我选择这种方法的原因是因为(1)我想在执行代码时阻止任何用户与表单的交互,以及(2)向用户提供处理正在进行的指示(I)不知道如何判断一段特定代码执行需要多长时间,因此选择了无限加载指示器gif)。
此外,关于在单独的线程中执行代码的主题......这不应该适用于任何代码,还是仅适用于长期运行的代码?
我真的很感激这方面的任何帮助!谢谢!
答案 0 :(得分:9)
最简单的方法之一是使用BackgroundWorker
组件。向表单添加BackgroundWorker,为DoWork
事件添加事件处理程序,并从那里调用长时间运行的函数。您可以通过调用BackgroundWorker组件上的RunWorkerAsync
方法在按钮单击事件处理程序中启动它。
为了知道操作何时准备就绪,请为RunWorkerCompleted
事件设置处理程序。
private void Button_Click(object sender, EventArgs e)
{
myBackgroundWorker.RunWorkerAsync();
}
private void myBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// long-running operation here; will execute on separate thread
}
private void myBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// operation is ready
}
答案 1 :(得分:4)
我会回答你问题的后半部分(因为Fredrik已经解释过BackgroundWorker):
不,除非任务长时间运行,否则将任务移动到单独的线程是没有意义的。
在单独的线程上运行任务总会产生额外的开销。可能需要更多的UI线程时间来启动线程并处理任务完成,然后它必须首先完成任务。
与任何编程技术一样,您必须权衡特定情况的成本和收益。
答案 2 :(得分:2)
我会根据自己的经验尝试回答你问题的第二部分。 通常只在以下三种情况之一中使用线程:
在系统调用(文件/套接字IO等)上阻塞显着时间段的操作
在长时间运行的操作中,不希望丢失UI响应。
有多个长时间运行的操作,需要利用多核环境。
正如Andrew Shepherd所说,使用Threads会产生开销。 线程使事情变得复杂。永远不要为了穿线而穿线。