15

为了论证的目的,将 UI 线程视为已调用Application.Run()或调用其中一个重载并运行活动消息循环的线程。

有没有办法检测我们当前是否在这样的线程上执行?

我想要这个的原因是因为我有一个具有长期运行的私有函数的类。该类本身已经是多线程的,并且此类的使用使得它可以从 UI 或后台线程进行处理时使用。这个功能也落入了这个网。但我不希望它阻塞 UI 线程。所以我想检测我是否在 UI 线程上运行,如果是,则将函数调用分叉到后台线程中(可能ThreadPool,但这不是本次讨论的问题)。这完全是行为良好的,但后台线程可能依赖于函数的输出,因此对它们来说阻塞更好,而 UI 线程以更“一劳永逸”的方式访问它。

4

6 回答 6

13

如果您可以访问 aForm或 a Control,则可以检查该InvokeRequired属性;false如果您在 UI 线程上,true如果您不在,这将返回。如果它发生在您无法检查 a 的上下文中Control,您可以轻松地在程序中设置一个可以检查的静态属性。Thread.CurrentThread在启动时存储对的引用,并Thread.CurrentThread在您需要知道时与该引用进行比较:

static class Program
{
    private static Thread _startupThread = null;

    [STAThread]
    static void Main()
    {
        _startupThread = Thread.CurrentThread;

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    public static bool IsRunningOnStartupThread()
    {
        return Thread.CurrentThread == _startupThread;
    }
}

通过打电话Program.IsRunningOnStartupThread,你会得到一个bool说法,如果你是或不是。

于 2009-07-19T07:26:46.630 回答
11

bool isMessageLoopThread = System.Windows.Forms.Application.MessageLoop;

于 2009-11-13T01:36:53.307 回答
7

我建议这是调用者应该做出的那种决定。您总是可以编写包装器方法以使其更容易 - 但这意味着您不会遇到调用者处于“奇怪”情况的问题(例如,您不知道的 UI 框架,或其他带有事件循环的东西) 而你为他们做出了错误的决定。

如果该方法需要在正确的线程中提供反馈,我会传入一个ISynchronizeInvoke(由 实现Control)以与 UI 无关的方式执行此操作。

于 2009-07-19T07:21:10.603 回答
6

请参阅检测在 C# 库的主线程中运行

于 2009-07-19T07:18:48.270 回答
4

WPF 还没有答案,因此记录在案,在 WPF 中,您可以使用的返回值Application.Current.Dispatcher.CheckAccess()来了解您是否在 GUI 线程上。

true如果当前线程是 WPF 中的 UI 线程,则返回。

于 2020-11-19T12:20:38.230 回答
3

您可以使用以下任何一种:

bool isUIThread1 = SynchronizationContext.Current != null;
bool isUIThread2 = Application.MessageLoop;
bool isUIThread3 = Thread.CurrentThread.GetApartmentState() == ApartmentState.STA;

为了SynchronizationContext.Current有一个值,应该显示第一种形式。它还可以SynchronizationContext.Current从非 UI 上下文设置为某些内容,也可以从 UI 上下文将其设置为 null(这通常被视为绕过 UI 死锁)。所以在某种程度上它并不完全可靠。

Application.MessageLoop是一个更好的选择,但这又需要启动消息泵(即显示的第一种形式)。

GetApartmentState可以在您的Main方法中使用,甚至在显示任何表单之前,但您需要[STAThread]设置 on Main。严肃的应用程序很少会错过这一点。在某种程度上,这种方法是最合理的。

出于所有实际目的,您可以使用其中任何一个。

于 2021-10-11T22:59:51.983 回答