有关Control.Invoke的困惑

hejialin666 2010-08-31 10:48:42
前几天遇到了问题:"线程间操作无效:从不是创建控件“XX”的线程访问它"。
从网上找到了解决办法,用Control.Invoke。

我在使用时发现了一个困惑的问题,代码如下:

public delegate void myDelegate(string strText);

//调用线程的方法
private void button4_Click(object sender, EventArgs e)
{
Thread th = new Thread(new ParameterizedThreadStart(RunLoop));
th.Start(10);
th.Name = "ForegroundThread";

}

//线程方法
public void RunLoop(object iMax)
{

String threadName = Thread.CurrentThread.Name;

for (int i = 0; i < Convert.ToInt32(iMax); i++)
{
textBox1.Invoke(new myDelegate(txtText), new Object[] { threadName + " count: " + i.ToString() });
}
}

//操作窗体控件的方法
public void txtText(string strText)
{
textBox1.Text += strText + "\r\n";
textBox2.Text = "1"; //困惑这一句,上面是textBox1.Invoke()调用的这个方法,这里操作textBox2控件
}


上面textBox2.Text = "1"; 这一句没有报错。用textBox1开的委托操作textBox2怎么没有报错的?
...全文
192 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
捷哥1999 2010-08-31
  • 打赏
  • 举报
回复
捷哥1999 2010-08-31
  • 打赏
  • 举报
回复
上面textBox2.Text = "1"; 这一句没有报错。用textBox1开的委托操作textBox2怎么没有报错的?

你这么想就不会困惑了,如果为TextBox1写了事件处理函数(其实就是一个委托类型的Event),可以为TextBox2指定它的事件处理函数一样为Textbox1的事件,对吧。

道理一样的,只要符合委托声明,就可以处理了。
bloodish 2010-08-31
  • 打赏
  • 举报
回复
Invoke的作用就是在拥有此控件的基础窗口句柄的线程上(UI线程)执行指定的委托。
在UI线程上,你可以访问textBox2的实例,也可以直接修改textBox2的Text
hejialin666 2010-08-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 dobzhansky 的回复:]
txtText 函数已经是在 UI 线程运行了

你分别在 runloop 和 txttext 函数种得到当前线程 ID 看看
[/Quote]
线程是同一个,我的问题是textBox1开的委托,委托中操作textBox2。困惑中
Dobzhansky 2010-08-31
  • 打赏
  • 举报
回复
txtText 函数已经是在 UI 线程运行了

你分别在 runloop 和 txttext 函数种得到当前线程 ID 看看
hejialin666 2010-08-31
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 wuyazhe 的回复:]
不是
Invoke和BeginInvoke的本质就是发消息。
消息循环是这样的,一个线程我们创建一个消息循环,这个窗体和窗体上的控件都依赖这个消息循环来工作,比如WM_PAINT,WM_LBUTTONDOWN等。而Invoke就是往调用的那个控件发消息,那个控件的消息和控件所在的窗体公用同一个消息循环的,也就是我们看到的Application.Run,一个窗体就只有一次,而这之后的控件都是在这……
[/Quote]
谢谢你,我刚查了一下MSDN上面对Control.Invoke的解释如下:
在拥有此控件的基础窗口句柄的线程上执行委托。
和你说的一样,非常感谢你的回答!
兔子-顾问 2010-08-31
  • 打赏
  • 举报
回复
不是
Invoke和BeginInvoke的本质就是发消息。
消息循环是这样的,一个线程我们创建一个消息循环,这个窗体和窗体上的控件都依赖这个消息循环来工作,比如WM_PAINT,WM_LBUTTONDOWN等。而Invoke就是往调用的那个控件发消息,那个控件的消息和控件所在的窗体公用同一个消息循环的,也就是我们看到的Application.Run,一个窗体就只有一次,而这之后的控件都是在这个消息循环的支持下工作的。所以这里的窗体和控件的invoke都是同一个地方处理的。效果一样的。
hejialin666 2010-08-31
  • 打赏
  • 举报
回复
是不是Form.Invoke就是在整个Form范围内适用。
textBox1.Invoke只是对textBox1适用?
兔子-顾问 2010-08-31
  • 打赏
  • 举报
回复
form.invoke和textbox1.invoke都是一样的,给调用的那个控件发消息。
hejialin666 2010-08-31
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wuyazhe 的回复:]
其实Control.Invoke很好理解。
我们2个线程,如何同步呢?
放一个变量,大家都来监视,当发现没有人占用变量,则自己可以设置标记,操作变量。当然可以,但是有更简单办法,就是利用消息机制。我们用的操作系统都是消息驱动的,那么你可以把同步作为一个消息传递给用友消息循环的线程,把并发操作变为顺序执行的操作。

Control.Invoke内部是通过对ui发送消息实现的,SendMess……
[/Quote]
谢谢你!
只是现在对Form.Invoke和具体控件textBox1.Invoke的区别理解的不好。
兔子-顾问 2010-08-31
  • 打赏
  • 举报
回复
其实Control.Invoke很好理解。
我们2个线程,如何同步呢?
放一个变量,大家都来监视,当发现没有人占用变量,则自己可以设置标记,操作变量。当然可以,但是有更简单办法,就是利用消息机制。我们用的操作系统都是消息驱动的,那么你可以把同步作为一个消息传递给用友消息循环的线程,把并发操作变为顺序执行的操作。

Control.Invoke内部是通过对ui发送消息实现的,SendMessage,发送后开始处理消息,直到处理完返回才继续执行。

Control.BeginInvoke内部是用PostMessage实现的,发完就不管了。所以是异步的。
兔子-顾问 2010-08-31
  • 打赏
  • 举报
回复
Control.CheckForIllegalCrossThreadCalls
尽量不要这么干。跨线程的检查是保证数据安全的关键,你关掉并不是一个明智选择。
hejialin666 2010-08-31
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 salecn 的回复:]
来学习一下!
[/Quote]
欢迎学习!
hejialin666 2010-08-31
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 peenyking 的回复:]
在窗口加载的时候 执行Control.CheckForIllegalCrossThreadCalls = false;

然后就可以在自定义线程中操作界面控件了
[/Quote]
这种方法不可取。我们查看CheckForIllegalCrossThreadCalls 这个属性的定义,就会发现它是一个static的,也就是说无论我们在项目的什么地方修改了这个值,他就会在全局起作用。而且像这种跨线程访问是否存在异常,我们通常都会去检查。如果项目中其他人修改了这个属性,那么我们的方案就失败了,
peenyking 2010-08-31
  • 打赏
  • 举报
回复
在窗口加载的时候 执行Control.CheckForIllegalCrossThreadCalls = false;

然后就可以在自定义线程中操作界面控件了
ljb3326 2010-08-31
  • 打赏
  • 举报
回复


路过 学习!!!!!!!!
hejialin666 2010-08-31
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 computerfox 的回复:]
上面textBox2.Text = "1"; 这一句没有报错。用textBox1开的委托操作textBox2怎么没有报错的?

你这么想就不会困惑了,如果为TextBox1写了事件处理函数(其实就是一个委托类型的Event),可以为TextBox2指定它的事件处理函数一样为Textbox1的事件,对吧。

道理一样的,只要符合委托声明,就可以处理了。
阿捷
[/Quote]
请问一个问题:你给的例子里用到Invoke时都是this.Invoke(),我这里是Control.Invoke()(具体是textBox1.Invoke)其中的区别在哪里?这两个方法似乎都能用。
renyouprince 2010-08-31
  • 打赏
  • 举报
回复
回帖有分

110,570

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧