gpt4 book ai didi

c# - 窗体 : Multiple Threads Updating UI at Same Time

转载 作者:太空狗 更新时间:2023-10-30 00:27:57 26 4
gpt4 key购买 nike

我继承了一些代码,这些代码有两个更新各种 WinForm 控件的非 UI 线程。
该代码使用 InvokeRequired 和 Invoke 来更新 UI;但是,我仍然偶尔会收到错误消息:跨线程操作无效:控件“lvReports”在创建时以外的线程上访问。

我怀疑我正在处理竞争条件,我需要在下面的方法中引入一个锁,但话虽如此,我可以找到许多关于如何从非 UI 线程安全地更新 UI 的示例,但没有示例或讨论如何处理在竞争场景中更新相同控件的两个线程。

所以我的问题是:如何重写下面的代码以在竞争条件下正确处理 UI 更新并且我需要从非 UI 线程更新 UI?

// two separate theads call this method in a instance of a WinForm
private void LoadReports()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(this.LoadReports));
}
else
{
// some code removed to keep exampe simple...
SetCtlVisible(lvReports, true);

if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate { lvReports.Refresh(); });
}
else
{
lvReports.Refresh();
}
}
}

delegate void SetVisibleCallback(Control ctl, bool visible);
private void SetCtlVisible(Control ctl, bool visible)
{
if (ctl.InvokeRequired)
{
SetVisibleCallback d = new SetVisibleCallback(SetCtlVisible);
ctl.Invoke(d, new object[] { ctl, visible });
}
else
{
ctl.Visible = visible;
}
}

以下是一些想法:this.InvokeRequired 是否随时与 ctl.InvokeRequired 不同?给定第一个 InvokeRequired 测试是否需要第二个?如果保留第一个 InvokeRequired,是否需要执行 SetCtlVisible?我应该删除第一个 InvokeRequired 并保留 else 子句中的所有代码吗?else 子句周围是否需要锁定?

最佳答案

像这样使用 InvokeRequired 是一种反模式。您知道此方法是从线程调用的,InvokeRequired 应该始终为真。

现在您可以使用它来解决您的问题。如果它是假的,那么就会出现严重的错误。抛出异常,调试器将停止并让您找出它无法正常工作的原因。并始终调用 Invoke(),调用一个小辅助方法来完成 LoadReports() 的其余部分。

另请注意,您在其余代码中使用错误。您知道 LoadReports() 的其余部分在 UI 线程上运行,您使用了 Invoke()。没有必要再次测试它,包括在 SetCtlVisible() 内部。

获得炸弹的典型原因是线程运行 LoadReports() 的时间过早,在窗体窗口创建之前。您需要将其互锁。窗体的 Load 事件是信号。

关于c# - 窗体 : Multiple Threads Updating UI at Same Time,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4567384/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com