简体   繁体   English

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

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

Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on. 跨线程操作无效:控件''是从创建该线程的线程之外的线程访问的。

My colleague is getting this exception on my code but i am not. 我的同事在我的代码上遇到此异常,但我没有。

On a form i have a control where a user is able to add some strings to a ListView. 在表单上,​​我有一个控件,用户可以在其中添加一些字符串到ListView。

Ive exposed a property in my control which returns the strings inside an XmlDocument. 我在控件中公开了一个属性,该属性返回XmlDocument中的字符串。

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

Get XML just takes the ListViewItem collection and formats them into an xml document. 获取XML只是获取ListViewItem集合并将其格式化为xml文档。

private XmlDocument GetXML()
{
    foreach(ListViewItem lvi in myListView.Items)   <-- Exception Here
    {
         // Do Stuff
    }
}
  1. Why am i getting this when just trying to read the list view? 尝试阅读列表视图时,为什么会得到这个? I thought cross thread exceptions were when you were trying to update the control from a separate thread. 我以为跨线程异常是当您尝试从单独的线程更新控件时。

  2. Why am i not getting this exception too? 为什么我也没有得到这个例外?

I thought cross thread exceptions were when you were trying to update the control from a separate thread 我以为跨线程异常是当您尝试从单独的线程更新控件时

Not true. 不对。 cross-thread exceptions occur when a control is accessed from not the main UI thread. 当不是从主UI线程访问控件时,就会发生跨线程异常。 The solution is trivial, check InvokeRequired and use Invoke . 解决方案很简单,请检查InvokeRequired并使用Invoke

As to why your friend hits this and you don't, is impossible to tell from the code you posted. 至于为什么你的朋友打了这个而你却不打呢,这不可能从你发布的代码中看出来。 It may be he compiles against different .Net target version, or it could be a race condition that your hardware doe snot hit (eg. he has more cores). 可能是他针对不同的.Net目标版本进行了编译,也可能是您的硬件受到打击的竞争条件(例如,他拥有更多的内核)。 Point is that is irrelevant. 一点是无关紧要的。 Your code needs to be thread safe as apparently GetXML can and is invoked from non main UI thread. 您的代码必须是线程安全的,显然GetXML可以并且从非主UI线程调用的。 It may well be that the responsibility to check for InvokeRequired should be on the caller, not the method. 检查InvokeRequired的责任很可能应该在调用方上,而不是在方法上。 Again, is impossible to tell from the code posted. 同样,从发布的代码中无法分辨。

When accessing Control in other than UI thread ( InvokeRequired returns true ) you should use Invoke insetead of direct call; 当在非UI线程中访问Control时( InvokeRequired返回true ),应该使用Invoke insetead直接调用; in order not to duplicate the code (for UI thread and for other threads) let's use extension method: 为了不重复代码(对于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();
    }
  }

I thought cross thread exceptions were when you were trying to update the control from a separate thread. 我以为跨线程异常是当您尝试从单独的线程更新控件时。

That's not correct. 那是不对的。 Remember, most of the WinForms controls are wrappers around Windows common controls. 请记住,大多数WinForms控件都是Windows通用控件的包装 And Windows controls use messages for both retrieving and updating, usually via SendMessage function . Windows控件通常通过SendMessage函数消息用于检索和更新。 So in general, although some calls could be safe to be performed from another thread, for the safety reasons Control.CheckForIllegalCrossThreadCalls is used in the control implementations on every get/set property or method call. 因此,通常来说,尽管可以安全地从其他线程执行某些调用,但是出于安全原因, Control.CheckForIllegalCrossThreadCalls用于每个get / set属性或方法调用的控件实现中。

Why am i not getting this exception too? 为什么我也没有得到这个例外?

It doesn't matter, you should not be doing that at the first place. 没关系,您不应该一开始就这样做。

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

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