剛才看到有人問為了winfrom中,在大數據綁定的時候出現畫面假死的狀態,為了解決這個問題希望通過再開一個線程來給控件綁定數據,可是畫面還是會假死。
現在看到的方法有
1.掩耳盜鈴法(Control.CheckForIllegalCrossThreadCalls = false;)
|
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
|
using
System;
using
System.Threading;
using
System.Windows.Forms;
namespace
ThreadTest
{
public
partial
class
Form1 : Form
{
public
Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls =
false
;
//這一行是關鍵
}
private
void
btnSet_Click(
object
sender, EventArgs e)
{
Thread t =
new
Thread(
new
ParameterizedThreadStart(SetTextBoxValue));
t.Start(
"Hello World"
);
}
void
SetTextBoxValue(
object
obj)
{
this
.textBox1.Text = obj.ToString();
}
}
}
|
這種方法是最方便,實現最簡單的方式,但是這樣等於是線程之間是去了限制,子線程能夠直接控制父線程的控件,會出現線程之間的沖突,不是好的實現方式
2.利用BackgroundWorker
|
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
33
34
35
36
37
38
|
using
System;
using
System.ComponentModel;
using
System.Windows.Forms;
namespace
ThreadTest
{
public
partial
class
Form1 : Form
{
public
Form1()
{
InitializeComponent();
}
private
void
btnSet_Click(
object
sender, EventArgs e)
{
//MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
using
(BackgroundWorker bw =
new
BackgroundWorker())
{
bw.RunWorkerCompleted +=
new
RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.DoWork +=
new
DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync(
"Hello World"
);
}
}
void
bw_DoWork(
object
sender, DoWorkEventArgs e)
{
//MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
e.Result = e.Argument;
//這里只是簡單的把參數當做結果返回,當然您也可以在這里做復雜的處理后,再返回自己想要的結果(這里的操作是在另一個線程上完成的)
}
void
bw_RunWorkerCompleted(
object
sender, RunWorkerCompletedEventArgs e)
{
//這時后台線程已經完成,並返回了主線程,所以可以直接使用UI控件了
this
.textBox1.Text = e.Result.ToString();
//MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
}
}
}
|
這種方式只能在異步結束后給控件賦值,
--即bw_DoWork是異步處理,異步處理過程中不能給控件賦值
--bw_RunWorkerCompleted方法中可以給控件賦值,可是這個過程不是異步的,如果在bw_RunWorkerCompleted中加上一個System.Threading.Thread.Sleep(3000);畫面還是會假死
3.不使用BackgroundWorker,自己來寫線程來實現類似於BackgroundWorker的處理
子線程給主線程成員賦值的迷惑
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 代碼中自己定義的按鈕(非顯示按鈕)
private
Button testBtn =
new
Button();
private
void
button1_Click(
object
sender, EventArgs e)
{
Thread thr =
new
Thread(ControlParent);
thr.Start();
}
private
void
ControlParent()
{
Thread.Sleep(3000);
// 給自己定義的按鈕賦值沒有問題
testBtn.Text =
"eeee"
;
// 給畫面上顯示的按鈕賦值,InvalidOperationException錯誤(這里迷糊了,子線程不能直接給主線程賦值,那么主線程是什么?)
this
.button1.Text =
"asda"
;
// InvalidOperationException!!!!!!!!!!!
}
|
這里的兩個按鈕,同樣是屬於一個類,只不過一個顯示在畫面上,另一個只定義了沒有顯示,為什么一個賦值成功,另一個就是敗了,求大哥大姐們來個破解之法,感激不盡。
PS:窗體的this.BeginInvoke只能不阻塞后面代碼的執行,不能解決畫面假死
