C# WinForms如何强制执行线程关联?

C# WinForms如何强制执行线程关联?,c#,multithreading,winforms,C#,Multithreading,Winforms,我原以为它是单线程单元机制,但指出它只适用于COM对象 有人知道Windows窗体使用什么机制来强制执行其线程关联吗?TL;DR:它将当前调用的线程id与用于创建控件窗口句柄的线程id进行比较。如果它们不同,则抛出异常 如果查看,您会发现一个名为CheckForIllegalCrossThreadCalls的属性: public static bool CheckForIllegalCrossThreadCalls { get { return checkForIlle

我原以为它是单线程单元机制,但指出它只适用于COM对象


有人知道Windows窗体使用什么机制来强制执行其线程关联吗?

TL;DR:它将当前调用的线程id与用于创建控件窗口句柄的线程id进行比较。如果它们不同,则抛出异常


如果查看,您会发现一个名为
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
在需要控件句柄的任何地方都可以访问,因此这是代码检查跨线程调用的逻辑位置

它利用
invokererequired
属性查看何时会发生跨线程调用

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进行比较。如果它们不同,则抛出异常


如果查看,您会发现一个名为
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
在需要控件句柄的任何地方都可以访问,因此这是代码检查跨线程调用的逻辑位置

它利用
invokererequired
属性查看何时会发生跨线程调用

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);
            }
        }
    }

这个问题可能让我难以理解,但您所说的“强制执行其线程关联”是什么意思?@adv12例如,假设您使用
Application.Run(new Form1())
启动一个表单,并且该表单上有一个名为
label1
的标签。现在假设您启动第二个线程。如果第二个线程试图更改label1.Text,您将得到一个错误。这通常被称为“线程关联”,您可以在这里获得更多信息:这个问题可能超出我的理解范围,但您所说的“强制执行其线程关联”是什么意思?@adv12例如,假设您使用
Application.Run(new Form1())
启动一个表单,并且该表单上有一个名为
label1
的标签。现在假设您启动第二个线程。如果第二个线程试图更改label1.Text,您将得到一个错误。这通常被称为“线程关联”,你可以在这里获得更多信息:写得不错。TL;DR-将当前调用的线程id与用于创建窗口的线程id进行比较。@AlexeiLevenkov我将无耻地窃取您的TL;DRI想知道它是否是基本控制类的一部分。非常感谢。写得不错。TL;DR-将当前调用的线程id与用于创建窗口的线程id进行比较。@AlexeiLevenkov我将无耻地窃取您的TL;DRI想知道它是否是基本控制类的一部分。非常感谢。