在窗体事件中执行BeginInvoke的一点疑惑

twtyypmb123 2017-04-02 12:58:53

private void button1_Click( object sender, EventArgs e )
{
progressBar1.Value++;
}

private void Form1_Shown( object sender, EventArgs e )
{

( new EventHandler( ( sdf, we ) =>
{
progressBar1.Value = 50;
System.Threading.Thread.Sleep( 100000 );
int i = 3;
} ) ).BeginInvoke( null, null, ( s ) =>
{
//Fun1();
return;
}, null );
//this.BeginInvoke( new Action( () =>
//{
// progressBar1.Value = 12;
// System.Threading.Thread.Sleep( 10000 );
// int i = 3;
//} ) );

//( new Thread( () =>
//{
// int i1 = 1;
// System.Threading.Thread.Sleep( 1000 );
// int j1 = 1;
//} ) ).Start();

int j = 123;
}


1. EventHandler的BeginInvoke中设置了进度条值,没有抛跨线程操作异常,是指这个在ui线程上执行?但是似乎界面没有被sleep锁死,而且值设置了,但是界面上没生效,点击了按钮,界面立马更新为正常的显示了,why?
2.把EventHandler注释,this.BeginInvoke注释取消掉,this.BeginInvoke会阻塞,证明this.BeginInvoke的委托在ui线程上运行?
谢谢解惑
...全文
386 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Forty2 2017-04-03
  • 打赏
  • 举报
回复
引用 4 楼 x3230835 的回复:
... 关于跨线程的ui操作会不会会不会抛异常,这个有没有确切的说法?还是说这个现象微软也没给出明确解释,总之为了保险起见用Control.begininvoke?
1、跨UI线程操作是不安全的,这个有文档,见https://msdn.microsoft.com/zh-cn/library/ms171728(v=vs.110).aspx 2、是不是一定会抛异常,我没有看到过的具体文档。我知道在Release编译环境下,不会抛出。而且在Debug环境下,试验可以验证某些操作也不抛出异常。 3、不抛异常不能说明它们正常工作。跨UI线程操作要遵循上述的文档指南。
twtyypmb123 2017-04-02
  • 打赏
  • 举报
回复
引用 3 楼 sp1234 的回复:
第一段代码,跟 UI 线程无关,这是其一。第一段代码,由于它可能不是在 UI 线程执行,它会比较诡异地去修改 Value 值,而UI 根本没有渲染,这正好是说明了这种 BeginInvoke 跟 Control.BeginInvoke 语法的区别。 第二段代码,阻塞了 UI 显示,整个界面运行都被卡死了(连鼠标移动事件之类的都被卡死了),证明虽然你写了 BeginInvoke,其实没用,这类代码貌似使用了 BeginInvoke 而其实还不如不写,因为都会卡死 UI 线程。
你说的“比较诡异地去修改 Value 值”我可以这样理解吗?现在代码只告诉了需要一个异步操作,并没有强迫this,所以程序只需要满足“异步执行”,即在程序认为合适的时候执行就算是正常,至于是ui线程还是托管线程池就看程序心情?
twtyypmb123 2017-04-02
  • 打赏
  • 举报
回复
引用 1 楼 Forty2 的回复:
1、并不是所有跨线程的UI操作都会抛出异常。 要观察它是否在UI线程上运行,打印他的Thread.CurrentThread.ManagedThreadId就清楚了。 private void Form1_Shown( object sender, EventArgs e ) { MessageBox.Show("UI线程ID:" + Thread.CurrentThread.ManagedThreadId); ( new EventHandler( ( sdf, we ) => { MessageBox.Show("当前线程ID:" + Thread.CurrentThread.ManagedThreadId); progressBar1.Value = 50; ... 2、this.BeginInvoke的委托在ui线程上运行? this.BeginInvoke本身并不阻塞。但它Invoke的代码在UI上运行,会造成UI不能及时响应。
关于跨线程的ui操作会不会会不会抛异常,这个有没有确切的说法?还是说这个现象微软也没给出明确解释,总之为了保险起见用Control.begininvoke?
  • 打赏
  • 举报
回复
第一段代码,跟 UI 线程无关,这是其一。第一段代码,由于它可能不是在 UI 线程执行,它会比较诡异地去修改 Value 值,而UI 根本没有渲染,这正好是说明了这种 BeginInvoke 跟 Control.BeginInvoke 语法的区别。 第二段代码,阻塞了 UI 显示,整个界面运行都被卡死了(连鼠标移动事件之类的都被卡死了),证明虽然你写了 BeginInvoke,其实没用,这类代码貌似使用了 BeginInvoke 而其实还不如不写,因为都会卡死 UI 线程。
  • 打赏
  • 举报
回复
这里常说的“BeginInvoke”是指 Control.BeginInvoke,而不是你第一段代码所写的 Delegate.BeginInvoke。字眼儿一样,但是是完全不同的意思。
Forty2 2017-04-02
  • 打赏
  • 举报
回复
1、并不是所有跨线程的UI操作都会抛出异常。 要观察它是否在UI线程上运行,打印他的Thread.CurrentThread.ManagedThreadId就清楚了。 private void Form1_Shown( object sender, EventArgs e ) { MessageBox.Show("UI线程ID:" + Thread.CurrentThread.ManagedThreadId); ( new EventHandler( ( sdf, we ) => { MessageBox.Show("当前线程ID:" + Thread.CurrentThread.ManagedThreadId); progressBar1.Value = 50; ... 2、this.BeginInvoke的委托在ui线程上运行? this.BeginInvoke本身并不阻塞。但它Invoke的代码在UI上运行,会造成UI不能及时响应。

110,536

社区成员

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

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

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