前言
使用Winfrom或WPF 製作桌面小程式的時候會用到
問題描述
按下Button時,畫面會卡住,畫面無法達到「按下按鈕 ->按鈕鎖定 ->執行商業邏輯 ->執行完畢 ->按鈕鎖定」這樣的基本效果
解法
使用BackgroundWorker可以解決上述的問題點
Sol:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public partial class MainWindow : Window
{
private BackgroundWorker worker = new BackgroundWorker();
public MainWindow()
{
InitializeComponent();
this.worker.DoWork += new DoWorkEventHandler(worker_DoWork);
this.worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (this.Button.IsEnabled == true) this.Button.IsEnabled = false;
worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (this.Button.IsEnabled == false) this.Button.IsEnabled = true;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
doSomeThing();
}
private void doSomeThing()
{
Task Task1 = Task.Run(() => {
/*
* 商業邏輯放這邊
*/
});
Task.WaitAll(Task1);
}
}
BackgroundWorker執行時更新UI控件的靜態擴展
由於有時候需要將Value傳回給UI的執行續,所以需要
使用方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class main
{
ComboBox cb = new ComboBox();
void main()
{
//方法1:使用lambda
cb.InvokeIfRequired(() =>
{
cb.Text = "hello";
});
//方法2:使用Action
cb.InvokeIfRequired(helloAction);
}
void helloAction()
{
cb.Text = "hello";
}
}
Sol:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static class Extensions
{
//非同步委派更新UI
public static void InvokeRequired(this Control control, MethodInvoker action)
{
if (control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action();
}
}
}
BackgroundWorker執行時更新UI控件的靜態擴展(WPF版本)
使用方式
1
2
3
4
private void UpdateProgress(string message)
{
ProgressLabel.InvokeIfNeeded(() => ProgressLabel.Content = message);
}
Sol:
1
2
3
4
5
6
7
8
9
10
11
public static void InvokeIfNeeded(this Control control, Action action)
{
if (control.Dispatcher.CheckAccess())
{
action();
}
else
{
control.Dispatcher.Invoke(action);
}
}