[英]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
}
}
尝试阅读列表视图时,为什么会得到这个? 我以为跨线程异常是当您尝试从单独的线程更新控件时。
为什么我也没有得到这个例外?
我以为跨线程异常是当您尝试从单独的线程更新控件时
不对。 当不是从主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.