为什么UI线程进入了阻塞状态,还能响应并执行其它线程的委托事件?

startququ 2012-04-27 11:32:47
例子我稍后贴上,有懂的能否先回答一下?
...全文
291 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
startququ 2012-04-27
  • 打赏
  • 举报
回复
但是,消息泵是一个消息执行完毕后,才能执行下一个消息。。。


MessageBox没有被退出前,怎么下一个消息,怎么可能被执行?

你可以注意代码中还有一句:

this.Title = "haha";


这句代码,在MessageBox被退出前,都没有被执行。



[Quote=引用 4 楼 的回复:]

MessageBox.Show虽然显示模式窗口,但消息泵还再运行(模式窗口也需要消息泵)。
消息泵的运行,使得Invoke有机会得到执行。
[/Quote]
gomoku 2012-04-27
  • 打赏
  • 举报
回复
MessageBox.Show虽然显示模式窗口,但消息泵还再运行(模式窗口也需要消息泵)。
消息泵的运行,使得Invoke有机会得到执行。
startququ 2012-04-27
  • 打赏
  • 举报
回复
下面代码,备注:
MainWindowLoaded函数,是主窗体的加载函数。
delay_zusai函数,是一个Button来触发的。


我想问的是:

System.Windows.MessageBox.Show("123", "abc");

这行代码运行后,UI线程进入了阻塞状态。

那么,为什么t1线程不断发过来的委托(颜色变化),还能够响应?





private void MainWindowLoaded(object sender, RoutedEventArgs e)
{

System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(delegate() { changecolor(); }));
t1.IsBackground = true;
t1.Start();



}

private void delay_zusai(object sender,RoutedEventArgs args)
{
System.Windows.MessageBox.Show("123", "abc");
this.Title = "haha";
}

private void changecolor()
{
int i = 0;
while (true)
{
System.Threading.Thread.Sleep(1000);
this.Change_Background(((i++ % 2 == 0) ? "Green" : "Red"));
}
}

delegate void Change_Background_Handle(string String_Color);
void Change_Background(string String_Color)
{
if (this.Dispatcher.Thread != System.Threading.Thread.CurrentThread)
{
this.Dispatcher.Invoke(new Change_Background_Handle(this.Change_Background), String_Color);
}
else
{
this.Background = new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)(System.Windows.Media.ColorConverter.ConvertFromString(String_Color)));
}
}





startququ 2012-04-27
  • 打赏
  • 举报
回复
什么意思,能否详细一点?

例子我正在写。

[Quote=引用 1 楼 的回复:]

线程同步
[/Quote]
tmd456 2012-04-27
  • 打赏
  • 举报
回复
线程同步
startququ 2012-04-27
  • 打赏
  • 举报
回复
我已经明白你的意思了。你把

System.Windows.MessageBox.Show("123", "abc");

的过程展开了,然后就非常清晰了。


[Quote=引用 7 楼 的回复:]

引用 5 楼 的回复:
System.Windows.MessageBox.Show("123", "abc");
this.Title = "haha";
这句代码,在MessageBox被退出前,都没有被执行。

因为this.Title = "haha"没有机会进入消息泵。
你把它放到你的线程里,Title就会改变。
记住没有消息泵,MessageBox就不能更新自己,就不……
[/Quote]
startququ 2012-04-27
  • 打赏
  • 举报
回复
我有点明白你的意思了。我再研究一下先。


[Quote=引用 7 楼 的回复:]

引用 5 楼 的回复:
System.Windows.MessageBox.Show("123", "abc");
this.Title = "haha";
这句代码,在MessageBox被退出前,都没有被执行。

因为this.Title = "haha"没有机会进入消息泵。
你把它放到你的线程里,Title就会改变。
记住没有消息泵,MessageBox就不能更新自己,就不……
[/Quote]
startququ 2012-04-27
  • 打赏
  • 举报
回复
UI线程为什么没有被阻塞?

我点击按钮后,程序UI线程就会执行函数:delay_zusai()这个函数。


然后,运行MessageBox。


那么,按道理接下来就是运行this.Title="haha"。

但是this.Title="haha",就是不出来,这样不是证明,UI线程阻塞在MessageBox那里了吗?


[Quote=引用 8 楼 的回复:]

引用 5 楼 的回复:

但是,消息泵是一个消息执行完毕后,才能执行下一个消息。。。


MessageBox没有被退出前,怎么下一个消息,怎么可能被执行?

你可以注意代码中还有一句:

this.Title = "haha";


这句代码,在MessageBox被退出前,都没有被执行。



引用 4 楼 的回复:

MessageBox.Show虽……
[/Quote]
qq13833254607 2012-04-27
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

但是,消息泵是一个消息执行完毕后,才能执行下一个消息。。。


MessageBox没有被退出前,怎么下一个消息,怎么可能被执行?

你可以注意代码中还有一句:

this.Title = "haha";


这句代码,在MessageBox被退出前,都没有被执行。



引用 4 楼 的回复:

MessageBox.Show虽然显示模式窗口,但消息泵还再运行……
[/Quote]
首先这个UI线程并没有被阻塞,其次this.Title = "haha"并不是消息
gomoku 2012-04-27
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
System.Windows.MessageBox.Show("123", "abc");
this.Title = "haha";
这句代码,在MessageBox被退出前,都没有被执行。
[/Quote]
因为this.Title = "haha"没有机会进入消息泵。
你把它放到你的线程里,Title就会改变。
记住没有消息泵,MessageBox就不能更新自己,就不能响应按钮点击。你可以把MessageBox.Show想象成如下代码:

EnableWindow(hParent, FALSE); //1
while( GetMessage(&msg, NULL, 0, 0) ) //2
{
if( !quitDialg && !IsDialogMessage(hCurrentDlg, &msg) ) //3
{
TranslateMessage(&msg);
DispatchMessage(&msg); //4
}
}
EnableWindow(hParent, TRUE);

//C#
this.Title = "haha";

1、禁用父窗口(因此点击父窗口等无效),
2、开始Modal消息泵循环,
3、如果是对消息框的操作,发送到消息框(相应消息框移动,消息框按钮点击等等...)
4、如果是非消息框消息,进行消息派送(其他线程发来的Invoke消息因此得到处理)

循环到消息框被关闭为止。
然后this.Title="haha"才有机会得到执行。
startququ 2012-04-27
  • 打赏
  • 举报
回复
继续顶顶。


谁能解释一下,点击按钮触发后,在MessageBox退出前,为什么:


this.Title="haha";这句不能被执行?

而颜色转换的委托事件,却可以不断地被执行?
1 事件订阅函数不是基于注解 Annotation 的 而是基于命名约定的 在Android 4 0之前的版本中 注解解析起来比较慢 事件响应函数默认以“onEvent”开始 可以在EventBus中修改这个值 但是不推荐这么干 2)事件响应有更多的线程选择 EventBus可以向不同的线程中发布事件 在ThreadMode 枚举中定义了4个线程 只需要在事件响应函数名称“onEvent”后面添加对应的线程类型名称 则还事件响应函数就会在对应的线程执行 比如事件函数“onEventAsync”就会在另外一个异步线程执行 ThreadMode定义的4个线程类型如下: PostThread:事件响应函数和事件发布在同一线程执行 这个是默认值 这样可以避免线程切换 MainThread:事件响应函数会在Android应用的主线程 大部分情况下都是UI线程执行 BackgroundThread:事件响应函数会在一个后台线程执行 如果事件发布函数不是在主线程中 则会立即在事件发布线程执行响应函数 如果事件发布函数在主线程中 EventBus则会在唯一的一个后台线程中按照顺序来执行所有的后台事件响应函数 上面的3种事件响应函数 应该能够很快的执行完 不然的话会阻塞各自的事件发布 async:事件响应函数在另外一个异步线程执行线程和发布线程线程相互独立 如果事件响应函数需要较长的时间来执行 则应该使用该模式 例如 网络访问等 需要注意的是 由于系统并行的限制 应该避免在同一时间触发大量的异步线程 EventBus使用一个线程池来提高线程的效率 ">1 事件订阅函数不是基于注解 Annotation 的 而是基于命名约定的 在Android 4 0之前的版本中 注解解析起来比较慢 事件响应函数默认以“onEvent”开始 可以在EventBus中修改这个值 但是不推荐这么干 2)事件响应有更多的线 [更多]

110,534

社区成员

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

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

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