Windows 窗體控件僅可在創(chuàng)建它們的線程上執(zhí)行,即它們不是線程安全的。如果要從后臺(tái)線程獲取或設(shè)置控件的屬性或?qū)丶{(diào)用方法,則必須將調(diào)用封送到創(chuàng)建該控件的線程。
在控件上有五個(gè)函數(shù)對(duì)于從任何線程調(diào)用都是安全的:InvokeRequired、Invoke、BeginInvoke、 EndInvoke 和 CreateGraphics。對(duì)于所有其他方法調(diào)用,應(yīng)使用上述調(diào)用方法之一。
默認(rèn)情況下,Windows 為您封送調(diào)用。但是,如果對(duì)某控件進(jìn)行多次調(diào)用,則您自己創(chuàng)建一個(gè)執(zhí)行這些調(diào)用的方法并且進(jìn)行跨線程調(diào)用將有效得多。通過調(diào)用 Control.Invoke 方法之一進(jìn)行跨線程調(diào)用。Invoke 方法采用對(duì)委托的引用。通常,此委托是 MethodInvoker 委托的一個(gè)實(shí)例。
InvokeRequired |
public bool InvokeRequired { get ; } 如果調(diào)用方對(duì)此控件進(jìn)行方法調(diào)用時(shí)必須調(diào)用 Invoke,則返回真。 |
BeginInvoke |
public IAsyncResult BeginInvoke(Delegate method) 在擁有此控件的基礎(chǔ)窗口句柄的線程上執(zhí)行給定的委托。異步調(diào)用該委托并且該方法立即返回。可從任何線程調(diào)用此方法,甚至可以從擁有該控件的句柄的線程上調(diào)用。如果該控件的句柄尚不存在,將沿該控件的父鏈向上查找,直到找到確實(shí)有窗口句柄的控件或窗體。如果無法找到相應(yīng)的句柄,BeginInvoke 將引發(fā)異常。此委托方法中的異常被視為未捕獲的異常,將發(fā)送給應(yīng)用程序的未捕獲的異常處理程序。 |
EndInvoke |
public Object EndInvoke(IAsyncResult asyncResult)
|
Invoke |
public Object Invoke(Delegate method) 在擁有此控件的基礎(chǔ)窗口句柄的線程上執(zhí)行給定的委托。同步調(diào)用該委托并且此方法在調(diào)用的方法返回后立即返回。返回值是調(diào)用的方法的結(jié)果。在控件所屬的同一個(gè)線程上調(diào)用此方法是錯(cuò)誤的。 |
下面的示例演示如何創(chuàng)建一個(gè)后臺(tái)線程,該線程使用 MethodInvoker 以固定時(shí)間間隔更新 ProgressBar 控件:


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

39

40

41

42

43

44

45

46


47

48

49



50



51

52

53

54

55

56

57
