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
浙公网安备 33010602011771号