当前位置:编程学习 > C#/ASP.NET >>

关于“线程间操作无效 从不是创建控件“___”的线程访问它”解决方法的疑惑

解决方法根据网友的资料一般提到了两种,但msdn的帮助提到了三种,有一种但我怎么验证也不行。先说一下经常讨论的两种:
(1)不使用委托:在构造函数或者窗体Load的代码里添加下面一句: 
Control.CheckForIllegalCrossThreadCalls = False
(2)委托方法的实现
private delegate void TestDelegate(); 
private void DelegateMethod(){ 
////label...... 

private void StartMethod(){ 
this.Invoke(new TestDelegate(DelegateMethod)) 


private button_click(...){ 
Thread thread = new Thread(new ThreadStart(StartMethod)); 
thread.Start(); 
}

这两种方法都没有问题,但是msdn还有一种即说用backgroundworker组件,这种方法那个例子没问题。
但是在下面这种情况就出问题了:
我通过串口(serialport)接收数据然后更新文本框,利用backgroundworker实现不成功。
描述一下我的程序,
在界面上放个textbox1,serialport1,backgroundworker1,button1,
然后在串口的datarecived中
   Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived

        ass1 = Me.SerialPort1.ReadLine()          'ass1为全局变量,接收串口数据,此步没问题
        Me.BackgroundWorker1.RunWorkerAsync()     '根据msdn我用BackgroundWorker1在textbox1完成显示
    End Sub

'在 BackgroundWorker1_RunWorkerCompleted中
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
       TextBox1.Text = "This text was set safely by BackgroundWorker."    '在textbox1中显示接收数据

    End Sub


     在执行到 TextBox1.Text = "This text was set safely by BackgroundWorker." 时提示“线程间操作无效 从不是创建控件“Textbox1”的线程访问它”。说明BackgroundWorker组件不能实现跨线程访问。

     但是在msdn例子里把 Me.BackgroundWorker1.RunWorkerAsync()     放在一个button的click中却可以正确运行,不提示跨线程访问问题。

   是不是BackgroundWorker组件不能避免类似上面描述的串口多线程访问的错误??那BackgroundWorker组件其实用在何种场合??

--------------------编程问答-------------------- 我学的vb.net,但与C#是互通的

我从vb.net给你说一下吧

窗体上有个textbox1控件,

从线程访问textbox1时用以下方法

delegate Sub Settextbox1f(Str as string)'声明对象

Sub SettextBox1(str as string)'访问textbox1
if me.textbox1.InvokeRequired then
Dim d as new Settextbox1f(AddressOf SettextBox1)
me.invoke(d,new object(){str})
else
textbox1.text=str
end sub


调用的时候就用settextbox1(str)就可以了。
--------------------编程问答-------------------- 谢谢,上面的方法我试过了,可以。
不过因为Vb .net中有个backgroundworker组件,msdn介绍说用它实现多线程比较简单也推荐用这种方法,但我测试在串口接收数据时就是不行,所以想问一下backgroundworker组件到底用在何种情况下的多线程跨线程访问才可以? --------------------编程问答-------------------- 顶!我也遇到这个问题,用方法一解决了,不过心理很不舒服。BGWorker组件还没用过,支持楼主。 --------------------编程问答-------------------- 加入form.CheckForIllegalCrossThreadCalls =false --------------------编程问答-------------------- Ding! --------------------编程问答-------------------- 牛X
顶 --------------------编程问答-------------------- 在执行到 TextBox1.Text = "This text was set safely by BackgroundWorker." 时提示“线程间操作无效 从不是创建控件“Textbox1”的线程访问它”。
那是因为BackGroundWorker处于独立于程序主线程的独立线程,无法直接操作窗体上的控件.

 Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived 

        ass1 = Me.SerialPort1.ReadLine()          'ass1为全局变量,接收串口数据,此步没问题 
        Me.BackgroundWorker1.RunWorkerAsync()    '根据msdn我用BackgroundWorker1在textbox1完成显示 
    End Sub 

'在 BackgroundWorker1_RunWorkerCompleted中 
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted 
      TextBox1.Text = "This text was set safely by BackgroundWorker."    '在textbox1中显示接收数据 

    End Sub 
改成如下试试:

delegate sub AA
dim S as String

 Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived 

        ass1 = Me.SerialPort1.ReadLine()     
S="This text was set safely by BackgroundWorker."
        Me.BeginInvoke(new AA(AdressOf SetText))
    End Sub 

'在 BackgroundWorker1_RunWorkerCompleted中 
Private sub SetText() 
      TextBox1.Text =S
       End Sub 
--------------------编程问答-------------------- 我看了MSDN的例子,backgroundworker根本就不是跨线程访问的。
我做了个测试,在BackgroundWorker1_RunWorkerCompleted设置一个死循环会发现整个程序都堵塞在哪里了。说明BackgroundWorker是属于主线程的。
我觉得例子所提的BackgroundWorker只是为了说明安全访问的目的,而没有说明跨线程访问。 --------------------编程问答-------------------- 4楼的方法是我提的第1中解决方法
1,7实际是我提到的第2种方法。

对7楼的一个回答有个疑问
那是因为BackGroundWorker处于独立于程序主线程的独立线程,无法直接操作窗体上的控件.

你的意思是这个BackGroundWorker是不同于主线程和串口接收线程的另外一个线程?出这错的原因是否是因为串口接收线程中调用BackGroundWorker导致的呢?

对8楼的回答一个疑问

我做了个测试,在BackgroundWorker1_RunWorkerCompleted设置一个死循环会发现整个程序都堵塞在哪里了。说明BackgroundWorker是属于主线程的。 

那么如果BackgroundWorker是属于主线程的,那么在BackgroundWorker的函数中操作textbox应该没问题吧?因为他们同属一个线程??

到底这个BackgroundWorker有何用呢??


--------------------编程问答-------------------- 我也遇到了这个问题,用BackgroundWorker没有成功,用代理的方式解决的。不过代理也只是使线程访问排序了,多线程的优点一点也体现不出来。
同顶吧 --------------------编程问答-------------------- 倒是 那个好一点呢
--------------------编程问答-------------------- --------------------编程问答-------------------- 2009年的帖子啊。。。
--------------------编程问答-------------------- Invoke。 --------------------编程问答--------------------
补充:.NET技术 ,  VB.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,