- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个 UserControl,上面有一个名为 mTreeView 的 TreeView 控件。我可以从多个不同的线程获取数据更新,这些会导致 TreeView 被更新。为此,我设计了以下模式:所有数据更新事件处理程序都必须获取锁,然后检查 InvokeRequired;如果是这样,请通过调用 Invoke 来完成工作。这是相关代码:
public partial class TreeViewControl : UserControl
{
object mLock = new object();
void LockAndInvoke(Control c, Action a)
{
lock (mLock)
{
if (c.InvokeRequired)
{
c.Invoke(a);
}
else
{
a();
}
}
}
public void DataChanged(object sender, NewDataEventArgs e)
{
LockAndInvoke(mTreeView, () =>
{
// get the data
mTreeView.BeginUpdate();
// perform update
mTreeView.EndUpdate();
});
}
}
我的问题是,有时候,在启动时,我会在 mTreeView.BeginUpdate() 上得到一个 InvalidOperationException,说 mTreeView 正在从一个不同于它创建的线程的线程更新。我在调用堆栈中返回到我的 LockAndInvoke,你瞧,c.InvokeRequired 是 true 但 else 分支被采用了!就好像在采用 else 分支后,InvokeRequired 在另一个线程上被设置为 true。
我的方法有什么问题吗?我该怎么做才能避免这种情况?
编辑:我的同事告诉我,问题是在创建控件之前 InvokeRequired 为 false,所以这就是它在启动时发生的原因。不过他不确定该怎么办。有什么想法吗?
最佳答案
这是一个标准的线程竞赛。在创建 TreeView 之前,您启动线程的时间过早。因此,您的代码将 InvokeRequired 视为 false,并在一瞬间之后创建 native 控件时失败。通过仅在窗体的 Load 事件触发时启动线程来解决此问题,这是保证所有控制句柄有效的第一个事件。
顺便说一下,代码中的一些误解。使用 lock 是不必要的,InvokeRequired 和 Begin/Invoke 都是线程安全的。 InvokeRequired 是一种反模式。您几乎总是知道该方法将由工作线程调用。所以使用 InvokeRequired 只在它为 false 时抛出异常。这将允许及早诊断此问题。
关于c# - 奇怪的 InvokeRequired 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11473496/
InvokeRequired 和 somecontrol.InvokeRequired 有什么区别? 像这样, delegate void valueDelegate(string value); p
这怎么可能?我有 Windows 窗体控件,从 System.Windows.Forms.Form 派生,WebBrowser 控件包含在此窗体中。 Webbrowser 对象实例是在表单的构造函数中
我有一个事件处理程序,我想在创建对象的原始线程中处理它,这样它就不会阻塞。使用表单,很容易使用 InvokeRequired 将其强制到原始线程。但是如果你的类不是表单,你怎么做呢? 谢谢, 下午 最
我知道您必须调用才能进行跨线程更新。但是,如果不需要 Invoke,您能否像需要 Invoke 时那样调用代码? 所以不是这个: if(rtbSearchResults.InvokeRequired)
这个问题在这里已经有了答案: What's wrong with calling Invoke, regardless of InvokeRequired? (6 个答案) 关闭 1 年前。 我的同
当我想在 Windows 窗体工作时使用委托(delegate)类进行调用时,我总是必须使用 InvokeRequired。没关系。但是谁在它工作时更改了 InvokeReuqired 属性。请检查这
UI 线程偶尔会在以下方法中的语句 'if (this.InvokeRequired)' 处挂起。 你能帮我找出问题的原因吗 public void OnModuleInitializationC
我一直在编写一个 API 来促进与串行端口的通信。我正在进行一些重构和一般清理,想知道是否有办法避免以下问题。 API 中的主类能够不断从端口读取数据,并在读取字节与特定正则表达式匹配时引发包含值的事
我想让我的 getter 线程安全。当我这样做时,出现错误: public ApplicationViewModel SelectedApplication { get
我来找你是想看看是否有人知道如何解决我在迁移到 ActiveMQ 时遇到的问题。我在这个项目中使用 ActiveMQ 发送通知(在 C# 中),在完成实现后我发现了一些关于线程问题的错误。 (我知道该
这是我的代码: foreach (var pathCartella in folderList) { try { // some operation i
我一直在寻找这个问题的答案,但似乎找不到满意的答案。也许这里有人可以启发我。 我有一个 BindingList 的后代存储对 SynchronizationContext 的引用对象以便在 UI 线程
我有一个 UserControl,上面有一个名为 mTreeView 的 TreeView 控件。我可以从多个不同的线程获取数据更新,这些会导致 TreeView 被更新。为此,我设计了以下模式:所有
这个问题在这里已经有了答案: Invoke or BeginInvoke cannot be called on a control until the window handle has been
在我的应用程序中,我有一个负责所有数据库操作的类。它从主类调用,并在操作完成后使用委托(delegate)调用方法。因为它是异步的,所以我必须在我的 GUI 上使用 invoke,所以我创建了一个简单
我是一名新手程序员,所以我在这里可能完全错了,但这个问题比它应该的更让我烦恼。 这实际上是 this 的跟进问题。 公认的答案是,您必须调用 InvokeRequired 以避免一些开销,因为您有可能
这个问题在这里已经有了答案: What's wrong with calling Invoke, regardless of InvokeRequired? (6 个答案) 关闭去年。 我知道,当从
我已经痛苦地意识到需要在事件驱动的 GUI 代码中编写以下代码模式的频率,其中 private void DoGUISwitch() { // cruisin for a bruisin' t
从.NET 4.0开始,TPL可以执行异步任务。如果您正在阅读msdn,则所有与窗体/UI交互的异步操作仍将使用InvokeRequire ... Invoke()模式。 我要问的是有原因吗?据我了解
首先,我在 Window.Forms 开发方面经验不足。但是我发现 InvokeRequired 检查,对于控件,在线程应用程序中使用时有点乏味。我创建了一个静态方法,我认为它可以解决我乏味的 Inv
我是一名优秀的程序员,十分优秀!