c# - 澄清使用匿名方法从单独的线程更新 GUI

标签 c# winforms multithreading user-interface

对于我目前的情况,我找到了一个看起来非常简单的解决方案。

我目前的情况是,我想在新线程上执行一些 I/O 密集型操作,这样我就不会陷入 GUI 线程的泥潭。作为我的表单的成员,我编写了一个函数,它已经完成了这些 I/O 操作,但是在 GUI 线程上运行它确实使应用程序使用起来很痛苦。所以我的计划是在一个新线程中运行这个函数。因此,我在我的表单中创建了一个 Thread 变量,并试图让它将该函数用作 ThreadStart 参数。不过,它似乎并不喜欢它。

我找到了一个优雅的解决方案,作为对另一个线程 here 的回应.

///...blah blah updating files
string newText = "abc"; // running on worker thread
this.Invoke((MethodInvoker)delegate {
    someLabel.Text = newText; // runs on UI thread
});
///...blah blah more updating files

从该响应的外观来看,我可以在新线程中运行此函数,然后在线程完成计算后使用匿名函数更新我的表单。不过,我只是不够好,无法填补该回复中的空白。

我读到的关于 Threads 的所有内容似乎都说我的 ThreadStart 函数需要是新类中的静态方法。该响应似乎表明我可以在我的 Form 类中完成它,以便 this 引用仍然引用我的 Form 实例。否则,如果我的 ThreadStart 参数是一个不同的类,我就必须传递对 Form 实例的引用,这似乎需要更多代码,对吧?

有人介意帮我填写该回复的上下文吗?提前致谢!

最佳答案

有很多方法可以做到这一点。一个非常简单、直截了当的方法已经存在了很多版本,就是使用 BackgroundWorker。 .它正是为这种情况而设计的。它有一个在后台线程中运行的 DoWork 方法,以及一个在 UI 线程中运行的工作完成后触发的 Completed 事件(因此您不必需要调用 invoke 或任何东西来用结果更新 UI)。它甚至内置支持报告进度(报告进度事件也在 UI 线程中运行),因此您可以轻松更新进度条或状态文本。

MSDN 有一些 examples还有,您可以通过一些简单的搜索找到更多。

通过 C# 4.0 提供的另一个选项是使用 Tasks。您可以启动一个将在后台线程中运行的新任务,然后您可以添加一个将在 UI 线程中运行的延续。

这是一个简单的例子:

private void button1_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(() => doStuffInBackground())
        .ContinueWith(task => updateUI(), TaskScheduler.FromCurrentSynchronizationContext());
}

private void updateUI()
{
    throw new NotImplementedException();
}

private void doStuffInBackground()
{
    throw new NotImplementedException();
}

您当然可以在我那里的实际 lambda 中做任何您想做的事情,或者您甚至可以删除 lambda 并直接将方法放入其中,只要您确保签名正确即可。如果你愿意,你也可以继续链接这些延续,例如,允许你执行任务 1,更新标签,然后执行任务 2,更新标签等。主要缺点是它不擅长更新进度条经常在循环内,BackgroundWorker 可以做到这一点。

关于c# - 澄清使用匿名方法从单独的线程更新 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11635277/

相关文章:

c# - 使用 C# Windows 10 是否可以判断视频/相机当前是否被任何应用程序使用?

c# - 如何在 C# 中中止套接字

c# - 通过反射设置自动属性的值

c# - 获取应用程序路径

c# - ASP.NET : How do I avoid duplicating Seed Data?

.net - WinForms:对象数据源使用最佳实践

winforms - Docker 可以(应该)用于 winforms 应用程序吗?

multithreading - 多个并发动态锁,获取锁失败则超时

python - python3如何从列表中删除线程对象

java - Spring 的线程