Winform按钮响应与UI冻结

做了些例子,演示在按钮响应中执行长时间操作

 

  1         // 同步调用延迟,窗口卡住直到结束,无法拖动
  2         private void button0_Click(object sender, EventArgs e)
  3         {
  4             button0.Enabled = false;
  5             label1.Text = "button0_Click:开始";   // 看不到
  6             Thread.Sleep(2000);
  7             label1.Text = "button0_Click:结束";
  8             button0.Enabled = true;
  9         }
 10 
 11         // 同步,窗口卡住直到结束,无法拖动(同上)
 12         private void button1_Click(object sender, EventArgs e)
 13         {
 14             button1.Enabled = false;
 15             label1.Text = "button1_Click:开始";   // 看不到
 16             int i = 0;
 17             while (i < 300)
 18             {
 19                 Thread.Sleep(20);
 20                 i++;
 21             }
 22             label1.Text = "button1_Click:结束";
 23             button1.Enabled = true;
 24         }
 25 
 26         // 同步,多了Application.DoEvents(),窗口不卡,可以拖动
 27         private void button2_Click(object sender, EventArgs e)
 28         {
 29             button2.Enabled = false;
 30             label1.Text = "button2_Click:开始";   // 能看到
 31             int i = 0;
 32             while (i < 300)
 33             {
 34                 Thread.Sleep(20);
 35                 Application.DoEvents();
 36                 i++;
 37             }
 38             label1.Text = "button2_Click:结束";
 39             button2.Enabled = true;
 40         }
 41 
 42         #region 按钮3
 43         // 陷入死锁,无法脱离,窗口卡死,无法拖动
 44         private void button3_Click(object sender, EventArgs e)
 45         {
 46             button3.Enabled = false;
 47             label1.Text = "button3_Click:开始";   // 能看到
 48             Task<string> res = GetResAsync_3();
 49 
 50             // 设断点能断到,看不到结果,陷入死锁:
 51             // 占住SychronizationContext,等待await执行完成
 52             label1.Text = $"button3_Click:结束,{res.Result}";
 53             button3.Enabled = true;
 54         }
 55 
 56         private async Task<string> GetResAsync_3()
 57         {
 58             await Task.Delay(2000);         // await等待获取SychronizationContext
 59             return "GetResAsync_3()";       // 设断点,执行不到
 60         }
 61         #endregion
 62 
 63         #region 按钮4
 64         // 使用Task.Run运行async方法,不会死锁,窗口卡住直到结束,无法拖动
 65         private void button4_Click(object sender, EventArgs e)
 66         {
 67             button4.Enabled = false;
 68             label1.Text = "button4_Click:开始";   // 能看到
 69             Task<string> res = Task.Run(GetResAsync_4);
 70             label1.Text = $"button4_Click:结束,{res.Result}"; // 能看到
 71             button4.Enabled = true;
 72         }
 73 
 74         private async Task<string> GetResAsync_4()
 75         {
 76             await Task.Delay(2000);
 77             return "GetResAsync_4()";
 78         }
 79         #endregion
 80 
 81         #region 按钮5
 82         // 将Click响应改为异步方法,不会死锁,窗口不卡,可以拖动
 83         private async void button5_Click(object sender, EventArgs e)
 84         {
 85             button5.Enabled = false;
 86             label1.Text = "button5_Click:开始";   // 能看到
 87             string res = await GetResAsync_5();
 88             label1.Text = $"button5_Click:结束,{res}"; // 能看到
 89             button5.Enabled = true;
 90         }
 91 
 92         private async Task<string> GetResAsync_5()
 93         {
 94             await Task.Delay(2000);
 95             return "GetResAsync_5()";
 96         }
 97         #endregion
 98 
 99         #region 按钮6
100         // 手动设置SynchronizationContext,不会死锁,窗口卡住直到结束,无法拖动
101         private void button6_Click(object sender, EventArgs e)
102         {
103             button6.Enabled = false;
104             label1.Text = "button6_Click:开始";   // 能看到
105             Task<string> res = GetResAsync_6();
106             label1.Text = $"button6_Click:结束,{res.Result}"; // 能看到
107             button6.Enabled = true;
108         }
109 
110         private async Task<string> GetResAsync_6()
111         {
112             //获取当前线程的SychronizationContext
113             SynchronizationContext syncContext = WindowsFormsSynchronizationContext.Current;
114             //设置当前线程的SychronizationContext为null
115             WindowsFormsSynchronizationContext.SetSynchronizationContext(null);
116             string t = await Task.Run(() => {
117                 Thread.Sleep(2000);
118                 return "GetResAsync() with SynchronizationContext";
119             });
120             //设置当前线程的SychronizationContext
121             WindowsFormsSynchronizationContext.SetSynchronizationContext(syncContext);
122             return t;
123         }
124         #endregion

 

posted on 2026-04-29 13:31  朱迎春  阅读(7)  评论(0)    收藏  举报