跨线程操作无效... - VB.NET
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2240702/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Crossthread operation not valid... - VB.NET
提问by lab12
I am using vb.net, and in my program I get this 'crossthread operation not valid' error when I run my backgroundworker that will make this textbox enabled true. My main sub will first turn the enabled to false, and when the backgroundworker runs it will turn it back true then exit. Why does it give me an error? FYI: There is more code to this but I don't want to make it any more confusing...
我正在使用 vb.net,并且在我的程序中,当我运行我的后台工作程序时,我会收到此“跨线程操作无效”错误,这将使此文本框启用为真。我的主要 sub 将首先将 enabled 变为 false,当后台工作程序运行时,它将返回 true 然后退出。为什么它给我一个错误?仅供参考:还有更多代码,但我不想让它变得更加混乱......
Here is the stack trace:
这是堆栈跟踪:
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)
and here is the exact error message:
这是确切的错误消息:
{"Cross-thread operation not valid: Control 'mainText' accessed from a thread other than the thread it was created on."}
Can someone please help me out!
有人可以帮帮我吗!
Thanks,
谢谢,
KEvin
凯文
回答by Dan Tao
The purpose of the BackgroundWorker
class is to perform work on a non-GUIthread while the GUI remains responsive. Unless you set Control.CheckForIllegalCrossThreadCalls
to false
(which you shouldn't do), or use Invoke
as suggested in the other answers (which I also wouldn't recommend), you're going to get an illegal cross-thread operation exception.
BackgroundWorker
该类的目的是在非 GUI线程上执行工作,同时 GUI 保持响应。除非您设置Control.CheckForIllegalCrossThreadCalls
为false
(您不应该这样做),或者Invoke
按照其他答案中的建议使用(我也不推荐),否则您将收到非法的跨线程操作异常。
If you want GUI-related "stuff" to happen whileyour BackgroundWorker
is running, I'd generally recommend using the BackgroundWorker.ReportProgress
method and attaching an appropriate handler to the BackgroundWorker.ProgressChanged
event. If you want something on the GUI to happen once the BackgroundWorker
is finished, then simply attach your handler to update the GUI to the BackgroundWorker.RunWorkerCompleted
event.
如果你想GUI相关的“东西”的出现,而你BackgroundWorker
正在运行,我一般建议您使用BackgroundWorker.ReportProgress
方法和安装合适的处理器的BackgroundWorker.ProgressChanged
事件。如果你想在GUI上的东西,一旦发生BackgroundWorker
被完成,然后简单地附上您的处理程序来更新GUI的BackgroundWorker.RunWorkerCompleted
事件。
回答by alex
Type the following code in the Form1_Load
(or whatever your form is) sub:
在Form1_Load
(或任何您的表单)子中键入以下代码:
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False
It fixes all problems with blocked cross-thread operations.
它修复了阻塞的跨线程操作的所有问题。
回答by SSpoke
Better way to this in VB.NET is to use a Extension
it makes very nice looking code for cross-threading GUI Control Calls.
在 VB.NET 中更好的方法是使用Extension
它为跨线程 GUI 控制调用制作非常漂亮的代码。
Just add this line of code to any Module you have.
只需将这行代码添加到您拥有的任何模块中即可。
<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
Now you can write Cross-Thread Control code that's only 1 line long for any control call.
现在您可以为任何控制调用编写只有 1 行长的跨线程控制代码。
Like this, lets say you want to clear a ComboBox and it's called from threads or without threads you can just use do this now
像这样,假设你想清除一个 ComboBox 并且它是从线程调用的,或者没有线程,你现在可以使用这样做
cboServerList.Invoke(Sub() cboServerList.Items.Clear())
Want to add something after you clear it?
清除后要添加一些内容吗?
cboServerList.Invoke(Sub() cboServerList.Items.Add("Hello World"))
回答by Fredrik M?rk
Where exactly do you set the Enabled
property? If you do it within the DoWork
event handler, this code is running on a different thread than the button was created on, which should give the exception that you experience. To get around this, you should use BeginInvoke
. For convenience it could be wrapped into a method, like so:
你究竟在哪里设置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
Now you can safely call that method to enable or disable any control from any thread:
现在您可以安全地调用该方法来启用或禁用来自任何线程的任何控制:
SetControlEnabled(someButton, False)
回答by jac
You cannot directly set a control's property that is on the UI thread from another thread. It can be done though, here is an example from msdn.
您不能直接从另一个线程设置 UI 线程上的控件的属性。不过可以做到,这里有一个来自 msdn 的例子。
Private Sub SetText(ByVal [text] As String)
' InvokeRequired required compares the thread ID of the'
' calling thread to the thread ID of the creating thread.'
' If these threads are different, it returns true.'
If Me.textBox1.InvokeRequired Then
Dim d As New SetTextCallback(AddressOf SetText)
Me.Invoke(d, New Object() {[text]})
Else
Me.textBox1.Text = [text]
End If
End Sub
回答by AlperDiktas
Your Form_Load () pls write below code part. All your problems will be solved.
你的 Form_Load () 请写在下面的代码部分。你所有的问题都会得到解决。
'## crossed-thread parts will not be controlled by this option...
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False
回答by Venkat
Suggest to use AutomationPeer.
建议使用AutomationPeer。
For example below code calls Execute button when I press F5 key. Similarly if you want a thread or Background worker to call an event or function you can use Automation Peer. In your case instead of button (Which I used here) you can use text box with its appropriate property to invoke.
例如,当我按下 F5 键时,下面的代码会调用 Execute 按钮。同样,如果您希望线程或后台工作者调用事件或函数,您可以使用自动化对等点。在您的情况下,而不是按钮(我在这里使用的),您可以使用具有适当属性的文本框来调用。
'Button name=btnExecute
'Imports System.Windows.Automation.Peers
'Imports System.Windows.Automation.Provider
If e.Key = Key.F5 Then
Dim peer As New ButtonAutomationPeer(btnExecute)
Dim invokeProv As IInvokeProvider = TryCast(peer.GetPattern(PatternInterface.Invoke), IInvokeProvider)
invokeProv.Invoke()
End If
Regards RV
问候房车
回答by CrazyCat Corporation
CheckForIllegalCrossThreadCalls = False