我原以爲這是Single-Threaded Apartment機制,但this documentation表示只適用於COM對象。WinForms如何強制執行線程關聯?
有誰知道什麼機制 Windows窗體用來強制其線程親和力?
我原以爲這是Single-Threaded Apartment機制,但this documentation表示只適用於COM對象。WinForms如何強制執行線程關聯?
有誰知道什麼機制 Windows窗體用來強制其線程親和力?
TL; DR:它將當前調用的線程ID與用於創建控件的窗口句柄的線程ID進行比較。如果它們不同,則會引發異常。
如果你看看the reference source for Windows.Forms.Control你會發現一個屬性調用CheckForIllegalCrossThreadCalls
:
public static bool CheckForIllegalCrossThreadCalls {
get { return checkForIllegalCrossThreadCalls; }
set { checkForIllegalCrossThreadCalls = value; }
}
每當一個句柄檢索這是用來:
public IntPtr Handle {
get {
if (checkForIllegalCrossThreadCalls &&
!inCrossThreadSafeCall &&
InvokeRequired) {
throw new InvalidOperationException(SR.GetString(SR.IllegalCrossThreadCall,
Name));
}
if (!IsHandleCreated)
{
CreateHandle();
}
return HandleInternal;
}
}
因爲Handle
被訪問的地方需要控制句柄,這是代碼檢查跨線程調用的合理位置。
它利用InvokeRequired
屬性來查看何時會發生跨線程調用。
InvokedRequired
本身有所涉及:
public bool InvokeRequired {
get {
using (new MultithreadSafeCallScope())
{
HandleRef hwnd;
if (IsHandleCreated) {
hwnd = new HandleRef(this, Handle);
}
else {
Control marshalingControl = FindMarshalingControl();
if (!marshalingControl.IsHandleCreated) {
return false;
}
hwnd = new HandleRef(marshalingControl, marshalingControl.Handle);
}
int pid;
int hwndThread = SafeNativeMethods.GetWindowThreadProcessId(hwnd, out pid);
int currentThread = SafeNativeMethods.GetCurrentThreadId();
return(hwndThread != currentThread);
}
}
}
好的寫作。 TL; DR-將當前調用的線程ID與用於創建窗口的線程ID進行比較。 –
@AlexeiLevenkov我會無恥地偷走你的TL; DR –
我想知道它是否是基礎控制類的一部分。非常感謝。 –
這個問題可能是在我的頭上,但你所說的「強制執行其線程親和力」是什麼意思? – adv12
@ adv12例如,假設您使用Application.Run(new Form1())'開始一個表單,並且該表單上有一個名爲'label1'的標籤。現在假設你啓動第二個線程。如果第二個線程試圖改變'label1.Text',你會得到一個錯誤。這就是所謂的「線程親和力」,你可以在這裏獲得更多信息:https://visualstudiomagazine.com/articles/2010/11/18/multithreading-in-winforms.aspx –