我们使用名为MV的MainWindow创建了一个应用程序。
当main启动时,它启动我们的StartProgram方法作为BackgroundWorker和Application.Run(MW);
MainWindow MW = new MainWindow();
BackgroundWorker.DoWork += (obj, e) => StartProgram(MW);
BackgroundWorker.RunWorkerAsync();
Application.Run(MW);
在StartProgram中,我们创建了Patient的实例,我们希望在listView1中显示它们。 我们通过调用此方法来实现这一点,该方法位于MW:
public void SetListSource(Patient p)
{
ListViewItem item = new ListViewItem("woohoo");
item.SubItems.Add("a");
listView1.Items.Add(item);
}
StartProgram在到达listView1.Items.Add(item)时停止;
我们的猜测是,它等待MW(MainWindow),但我们无法弄清楚如何解决它。 我们在MW中有一个按钮,它有一些类似的功能,除了它只发送" 1"和" a"到listView1。
private void Sort_Button_Click(object sender, EventArgs e)
{
ListViewItem item = new ListViewItem("1");
item.SubItems.Add("a");
listView1.Items.Add(item);
}
有人知道如何使SetListSource(...)作为Sort_Button_Click(...)工作吗?
修改 解决了Invoke
答案 0 :(得分:1)
您无法直接从其他线程修改您的GUI 。您需要使用委托并调用您的控件。在你的主题中你必须做:
CONTROL.Invoke(new Action(() =>
{
CONTROL.Items.Add(item);
}
));
来源:
答案 1 :(得分:0)
你可以使用Invoke
,但这可能是不必要的。您可以改为使用BackgroundWorker.RunWorkerCompleted
事件:
BackgroundWorker.DoWork +=
(s, e) =>
{
e.Result = DoAllTheComplicatedWork();
}
BackgroundWorker.RunWorkerCompleted +=
(s, e) =>
{
// Back on the UI thread, we can do whatever we want
listView1.Items.Add(((SomeDTO)e.Result).Patient);
}
BackgroundWorker.RunWorkerAsync();
或者,您可以使用await
完成整个事情:
MW.Load += async (s, e)
{
var result = await Task.Run(() => SomeCPUWork());
listView1.Items.Add(((SomeDTO)e.Result).Patient);
}
关键是,你真的想要在UI和背景中需要做的事情之间进行分离。我绝对不会将表单(或任何其他控件)传递给任何应该在不同线程上执行的方法。