我原以为是Single-Threaded Apartment机制,但是this documentation表示只适用于COM对象。
有谁知道Windows Forms用于强制执行其线程关联的机制?
答案 0 :(得分:4)
TL; DR:它将当前调用的线程id与用于创建控件的Window句柄的线程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);
}
}
}