交叉操作无效... - VB.NET

lab*_*b12 13 vb.net multithreading visual-studio-2010

我正在使用vb.net,并且在我的程序中,当我运行我的后台工作程序时,我会得到这个'crossthread操作无效'错误,这将使此文本框启用为true.我的主要sub将首先将enabled设置为false,当backgroundworker运行时,它将返回true,然后退出.为什么它会给我一个错误?仅供参考:有更多的代码,但我不想让它更令人困惑......

这是堆栈跟踪:

at System.Windows.Forms.Control.get_Handle()
   at System.Windows.Forms.Control.OnEnabledChanged(EventArgs e)
   at System.Windows.Forms.Control.set_Enabled(Boolean value)
   at Helium.Form1.BackgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in C:\Users\Kevin\documents\visual studio 2010\Projects\Helium\Helium\Form1.vb:line 167
   at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
   at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
Run Code Online (Sandbox Code Playgroud)

这是确切的错误消息:

{"Cross-thread operation not valid: Control 'mainText' accessed from a thread other than the thread it was created on."}
Run Code Online (Sandbox Code Playgroud)

有人可以帮帮我!

谢谢,

凯文

Dan*_*Tao 21

BackgroundWorker该类的目的是在GUI保持响应的同时在非GUI线程上执行工作.除非您设置Control.CheckForIllegalCrossThreadCallsfalse(您不应该这样做),或者Invoke按照其他答案(我也不建议)的建议使用,否则您将获得非法的跨线程操作异常.

如果你想GUI相关的"东西"的出现,而BackgroundWorker正在运行,我一般建议您使用BackgroundWorker.ReportProgress方法和安装合适的处理器的BackgroundWorker.ProgressChanged事件.如果你想在GUI上的东西,一旦发生BackgroundWorker完成,然后简单地附上您的处理程序来更新GUI的BackgroundWorker.RunWorkerCompleted事件.


小智 13

Form1_Load(或任何形式)sub中键入以下代码:

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False
Run Code Online (Sandbox Code Playgroud)

它修复了阻塞的跨线程操作的所有问题.

  • 请注意,这个答案是*bad*,如[在将调试期间将CheckForIllegalCrossThreadCalls设置为false以避免交叉线程错误这样安全吗?](http://stackoverflow.com/questions/13345091/is-it-safe-只是对设置checkforillegalcrossthreadcalls到假到避免交叉-T).**请不要使用它,而是修复代码的问题(即创建适当的代表).** (5认同)

Fre*_*örk 11

你在哪里设置了Enabled房产?如果您在DoWork事件处理程序中执行此操作,则此代码在与创建按钮不同的线程上运行,这应该提供您遇到的异常.要解决这个问题,你应该使用BeginInvoke.为方便起见,它可以包装到一个方法中,如下所示:

Private Sub SetControlEnabled(ByVal ctl As Control, ByVal enabled As Boolean)
    If ctl.InvokeRequired Then
        ctl.BeginInvoke(New Action(Of Control, Boolean)(AddressOf SetControlEnabled), ctl, enabled)
    Else
        ctl.Enabled = enabled
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)

现在,您可以安全地调用该方法来启用或禁用任何线程的任何控件:

SetControlEnabled(someButton, False)
Run Code Online (Sandbox Code Playgroud)


SSp*_*oke 9

在VB.NET中更好的方法是使用Extension它为跨线程GUI控制调用制作非常漂亮的代码.

只需将此行代码添加到您拥有的任何模块中即可.

<System.Runtime.CompilerServices.Extension()> _
Public Sub Invoke(ByVal control As Control, ByVal action As Action)
    If control.InvokeRequired Then
        control.Invoke(New MethodInvoker(Sub() action()), Nothing)
    Else
        action.Invoke()
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)

现在,您可以编写跨线程控制代码,该代码对于任何控制调用只有1行长.

像这样,让我们​​说你要清除一个ComboBox,它是从线程调用的,或者没有线程,你现在就可以使用它

cboServerList.Invoke(Sub() cboServerList.Items.Clear())
Run Code Online (Sandbox Code Playgroud)

想要在清除后添加一些东西吗?

cboServerList.Invoke(Sub() cboServerList.Items.Add("Hello World"))
Run Code Online (Sandbox Code Playgroud)