c# – Winforms多线程UI *** 作的随机跨线程 *** 作异常

c# – Winforms多线程UI *** 作的随机跨线程 *** 作异常,第1张

概述出于某种原因,这种安全的方法引发了一个典型的例外. Cross-thread operation not valid: Control ‘statusLabel’ accessed from a thread other than the thread it was created on. 显然,当需要调用时,此代码应通过Invoke调用匿名方法. 但每隔一段时间就会发生异常. 有人有过类似的问题 出于某种原因,这种安全的方法引发了一个典型的例外.

Cross-thread operation not valID:
Control ‘statusLabel’ accessed from a
thread other than the thread it was
created on.

显然,当需要调用时,此代码应通过Invoke调用匿名方法.
但每隔一段时间就会发生异常.

有人有过类似的问题吗?

private voID SetProgressbarValue(int progresspercentage)    {        Action setValue = () =>         {            var value = progresspercentage;            if (progresspercentage < 0)                value = 0;            else if (progresspercentage > 100)                value = 100;            statusProgressbar.Value = value;            statusLabel.Text = string.Format("{0}%",value);        };        if (Invokerequired)            Invoke(setValue);        else            setValue();    }

[UPDATE2]
执行John Saunders’s suggestion后,仍然遇到同样的错误

at System.windows.Forms.Control.get_Handle()at System.windows.Forms.Control.SetBoundscore(Int32 x,Int32 y,Int32 wIDth,Int32 height,BoundsspecifIEd specifIEd)at System.windows.Forms.ToolStrip.SetBoundscore(Int32 x,BoundsspecifIEd specifIEd)at System.windows.Forms.ToolStrip.System.windows.Forms.Layout.IArrangedElement.SetBounds(Rectangle bounds,BoundsspecifIEd specifIEd)at System.windows.Forms.Layout.DefaultLayout.xLayoutDockedControl(IArrangedElement element,Rectangle newElementBounds,Boolean measureOnly,ref Size preferredSize,ref Rectangle remainingBounds)at System.windows.Forms.Layout.DefaultLayout.LayoutDockedControls(IArrangedElement container,Boolean measureOnly)at System.windows.Forms.Layout.DefaultLayout.xLayout(IArrangedElement container,ref Size preferredSize)at System.windows.Forms.Layout.DefaultLayout.LayoutCore(IArrangedElement container,LayoutEventArgs args)at System.windows.Forms.Layout.LayoutEngine.Layout(Object container,LayoutEventArgs layoutEventArgs)at System.windows.Forms.Control.OnLayout(LayoutEventArgs levent)at System.windows.Forms.ScrollableControl.OnLayout(LayoutEventArgs levent)at System.windows.Forms.Form.OnLayout(LayoutEventArgs levent)at System.windows.Forms.Control.Performlayout(LayoutEventArgs args)at System.windows.Forms.Control.System.windows.Forms.Layout.IArrangedElement.Performlayout(IArrangedElement affectedElement,String affectedProperty)at System.windows.Forms.Layout.LayoutTransaction.Dolayout(IArrangedElement elementTolayout,IArrangedElement elementCausingLayout,String property)at System.windows.Forms.Control.Performlayout(LayoutEventArgs args)at System.windows.Forms.Control.System.windows.Forms.Layout.IArrangedElement.Performlayout(IArrangedElement affectedElement,String property)at System.windows.Forms.ToolStripItem.InvalIDateItemLayout(String affectedProperty,Boolean invalIDatePainting)at System.windows.Forms.ToolStripItem.OnTextChanged(EventArgs e)at System.windows.Forms.ToolStripItem.set_Text(String value)at App.Image.Replace.ReplacementimageProcessForm.<>c__displayClassa.<>c__displayClassc.<SetProgressbarValue>b__9() in ReplacementimageProcessForm.cs: line 147at App.Image.Replace.ReplacementimageProcessForm.InvokeIfNecessary(Control control,Action setValue) in ReplacementimageProcessForm.cs: line 156at App.Image.Replace.ReplacementimageProcessForm.<>c__displayClassa.<SetProgressbarValue>b__7() in ReplacementimageProcessForm.cs: line 145at App.Image.Replace.ReplacementimageProcessForm.InvokeIfNecessary(Control control,Action setValue) in ReplacementimageProcessForm.cs: line 156at App.Image.Replace.ReplacementimageProcessForm.SetProgressbarValue(Int32 progresspercentage) in ReplacementimageProcessForm.cs: line 132at App.Image.Replace.ReplacementimageProcessForm.replacer_BeginReplace(Object sender,EventArgs e) in ReplacementimageProcessForm.cs: line 74at App.Image.Replace.documentReplacer.OnBeginReplace() in IdocumentReplacer.cs: line 87at App.Image.Replace.documentReplacer.Replace(Int32 documentID,String replacementdocumentPath) in IdocumentReplacer.cs: line 123

[更新]这是问题完整性的堆栈跟踪.

at System.windows.Forms.Control.get_Handle()at System.windows.Forms.Control.SetBoundscore(Int32 x,Boolean invalIDatePainting)at System.windows.Forms.ToolStripItem.OnTextChanged(EventArgs e)at System.windows.Forms.ToolStripItem.set_Text(String value)at App.Image.Replace.ReplacementimageProcessForm.<>c__displayClass8.<SetProgressbarValue>b__7() in ReplacementimageProcessForm.cs: line 114at App.Image.Replace.ReplacementimageProcessForm.SetProgressbarValue(Int32 progresspercentage) in ReplacementimageProcessForm.cs: line 119at App.Image.Replace.ReplacementimageProcessForm.replacer_BeginReplace(Object sender,EventArgs e) in ReplacementimageProcessForm.cs: line 76at App.Image.Replace.documentReplacer.OnBeginReplace() in IdocumentReplacer.cs: line 72at App.Image.Replace.documentReplacer.Replace(Int32 documentID,String replacementdocumentPath) in IdocumentReplacer.cs: line 108
解决方法 这可能与您的情况直接相关,也可能不直接相关,但可以提供线索.要记住windows窗体的一个重要漏洞抽象是在实际需要之前不会创建窗口句柄. Handle属性仅在第一次get调用时创建真正的windows hwnd,当实例化Control派生对象(如windows窗体)时不会发生这种情况. (毕竟,Control-derived对象只是一个.NET类.)换句话说,它是一个懒惰地初始化的属性.

我以前被这个烧过:我的问题是我在UI线程上正确实例化了一个表单,但是直到数据从已经进行的Web服务调用返回时我才显示它.在工作线程上运行.这种情况是,在工作线程完成其工作之后,作为Invokerequired检查的一部分访问它之前,没有人曾要求表单的Handle.所以我的后台工作者线程询问了表单:我需要Invokerequired吗?然后表单的Invokerequired实现说:好吧,让我看一下我的Handle,这样我就可以看到我的内部hwnd创建了什么线程,然后我会看看你是否在同一个线程上.然后Handle实现说:我还不存在,所以让我现在为自己创造一个hwnd. (你会看到它的发展方向.请记住,我们仍然在后台线程上,无辜地访问Invokerequired属性.)

这导致Handle(和它的底层hwnd)在工作线程上创建,我没有拥有它,并且没有设置消息泵来处理windows消息.结果:当我对以前隐藏的窗口进行其他调用时,我的应用程序被锁定,因为这些调用是在主UI线程上进行的,这合理地假设所有其他的Control派生对象也已在此线程上创建.在其他情况下,这可能会导致奇怪的跨线程异常,因为Invokerequired会意外返回false,因为Handle是在与实例化表单的线程不同的线程上创建的.

但有时候只是.我有一些功能,用户可以通过菜单使表单显示()本身,然后它会在自己填充背景中的数据时自动禁用(显示一个跳动动画).如果他们首先这样做,那么一切都会好的:Handle是在UI线程上创建的(在菜单项的事件处理程序中),因此当工作线程完成从Web服务检索数据时,Invokerequired按预期运行.但是如果我定期运行的后台线程(它是一个事件调度程序,类似于Outlook中的Event Reminder对话框)访问Web服务并尝试d出表单,并且用户还没有Show()n,那么工作者线程的触摸Invokerequired将导致上述的引起胃灼热的行为.

祝你的heisenBUG好运!

总结

以上是内存溢出为你收集整理的c# – Winforms多线程UI *** 作的随机跨线程 *** 作异常全部内容,希望文章能够帮你解决c# – Winforms多线程UI *** 作的随机跨线程 *** 作异常所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1240758.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-06
下一篇2022-06-06

发表评论

登录后才能评论

评论列表(0条)

    保存