繁体   English   中英

不一致的“跨线程操作无效”异常

[英]Inconsistent “Cross-thread operation not valid” exception

跨线程操作无效:控件''是从创建该线程的线程之外的线程访问的。

我的同事在我的代码上遇到此异常,但我没有。

在表单上,​​我有一个控件,用户可以在其中添加一些字符串到ListView。

我在控件中公开了一个属性,该属性返回XmlDocument中的字符串。

public XmlDocument XmlConfig
{
    get
    {
        return GetXML();
    }
}

获取XML只是获取ListViewItem集合并将其格式化为xml文档。

private XmlDocument GetXML()
{
    foreach(ListViewItem lvi in myListView.Items)   <-- Exception Here
    {
         // Do Stuff
    }
}
  1. 尝试阅读列表视图时,为什么会得到这个? 我以为跨线程异常是当您尝试从单独的线程更新控件时。

  2. 为什么我也没有得到这个例外?

我以为跨线程异常是当您尝试从单独的线程更新控件时

不对。 当不是从主UI线程访问控件时,就会发生跨线程异常。 解决方案很简单,请检查InvokeRequired并使用Invoke

至于为什么你的朋友打了这个而你却不打呢,这不可能从你发布的代码中看出来。 可能是他针对不同的.Net目标版本进行了编译,也可能是您的硬件受到打击的竞争条件(例如,他拥有更多的内核)。 一点是无关紧要的。 您的代码必须是线程安全的,显然GetXML可以并且从非主UI线程调用的。 检查InvokeRequired的责任很可能应该在调用方上,而不是在方法上。 同样,从发布的代码中无法分辨。

当在非UI线程中访问Control时( InvokeRequired返回true ),应该使用Invoke insetead直接调用; 为了不重复代码(对于UI线程和其他线程),我们使用扩展方法:

  private XmlDocument GetXML() {
    myListView.InvokeSynchronized(() => {
      foreach(ListViewItem lvi in myListView.Items) {
        // Do Stuff
      }
    });
  }

  ...

  public static class ControlAsyncExtensions {
    public static void InvokeSynchronized(this Control control, Action action) {
      if (Object.ReferenceEquals(null, action))
        throw new ArgumentNullException("action");

      if (Object.ReferenceEquals(null, control))
        action();
      else if (control.InvokeRequired)
        control.Invoke(action);
      else
        action();
    }
  }

我以为跨线程异常是当您尝试从单独的线程更新控件时。

那是不对的。 请记住,大多数WinForms控件都是Windows通用控件的包装 Windows控件通常通过SendMessage函数消息用于检索和更新。 因此,通常来说,尽管可以安全地从其他线程执行某些调用,但是出于安全原因, Control.CheckForIllegalCrossThreadCalls用于每个get / set属性或方法调用的控件实现中。

为什么我也没有得到这个例外?

没关系,您不应该一开始就这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM