如何判断一个线程是否是c#中的主线程?

时间:2022-08-11 20:58:51

I know there are other posts that say you can create a control and then check the InvokeRequired property to see if the current thread is the main thread or not.

我知道还有其他一些文章说,您可以创建一个控件,然后检查InvokeRequired属性,看看当前线程是否是主线程。

The problem is that you have no way of knowing if that control itself was created on the main thread.

问题是,您无法知道控制本身是否在主线程上创建。

I am using the following code to tell if a thread is the main thread (the thread that started the process):

我使用下面的代码来判断一个线程是否是主线程(启动进程的线程):

if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA ||
    Thread.CurrentThread.ManagedThreadId != 1 ||
    Thread.CurrentThread.IsBackground || Thread.CurrentThread.IsThreadPoolThread)
{
    // not the main thread
}

Does anyone know a better way? It seems like this way might be prone to errors or break in future versions of the runtime.

有人知道更好的方法吗?这样看来,在运行时的将来版本中可能会出现错误或中断。

5 个解决方案

#1


37  

You could do it like this:

你可以这样做:

// Do this when you start your application
static int mainThreadId;

// In Main method:
mainThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;

// If called in the non main thread, will return false;
public static bool IsMainThread
{
    get { return System.Threading.Thread.CurrentThread.ManagedThreadId == mainThreadId; }
}

EDIT I realized you could do it with reflection too, here is a snippet for that:

我意识到你也可以用反射来做,这里有一个片段:

public static void CheckForMainThread()
{
    if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA &&
        !Thread.CurrentThread.IsBackground && !Thread.CurrentThread.IsThreadPoolThread && Thread.CurrentThread.IsAlive)
    {
        MethodInfo correctEntryMethod = Assembly.GetEntryAssembly().EntryPoint;
        StackTrace trace = new StackTrace();
        StackFrame[] frames = trace.GetFrames();
        for (int i = frames.Length - 1; i >= 0; i--)
        {
            MethodBase method = frames[i].GetMethod();
            if (correctEntryMethod == method)
            {
                return;
            }
        }
    }

    // throw exception, the current thread is not the main thread...
}

#2


16  

If you're using Windows Forms or WPF, you can check to see if SynchronizationContext.Current is not null.

如果您使用的是Windows窗体或WPF,您可以检查是否同步上下文。目前不是零。

The main thread will get a valid SynchronizationContext set to the current context upon startup in Windows Forms and WPF.

在Windows窗体和WPF上启动时,主线程将获得一个有效的同步上下文设置到当前上下文。

#3


10  

Here is another option:

这是另一个选择:

if (App.Current.Dispatcher.Thread == System.Threading.Thread.CurrentThread)
{
    //we're on the main thread
}

Works for me.

为我工作。

EDIT : Forgot to mention that this works only in WPF. I was searching SO for the WPF case, and I didn't notice that this question is general .NET. Another option for Windows Forms could be

编辑:忘了说这只在WPF中有效。我搜索的是WPF的例子,我没有注意到这个问题是。net的。Windows窗体的另一个选择可能是。

if (Application.OpenForms[0].InvokeRequired)
{
    //we're on the main thread
}

Of course, you should first make sure that there is at least one Form in the application.

当然,您应该首先确保应用程序中至少有一个表单。

#4


3  

Try this one if (Application.MessageLoop) . I think it is rare case to have more than 1 thread to process messages

试试这个if (Application.MessageLoop)。我认为有超过1个线程来处理消息是很少见的。

#5


2  

In my experience, if you attempt to create a dialog from another thread other than the main thread then windows gets all confused and things start going crazy. I tried to do this once with a status window to show the status of the background thread (as well as many other times someone would toss up a dialog from a background thread - and one that did have a Message Loop) - and Windows just started doing "random" things in the program. I'm pretty sure there was some unsafe handling of something going on. Had issues with clicking on the form and the wrong thread handling the messages...

根据我的经验,如果你试图从其他线程创建一个对话框,而不是主线程,那么windows就会变得混乱,事情就会变得疯狂起来。我试着做这一次的状态窗口显示后台线程的状态(以及其他许多次有人扔了一个对话框从一个后台线程,确实有一个消息循环)——和Windows只是开始做“随机”的计划。我很确定有一些不安全的处理。有问题,点击表单和错误的线程处理消息…

So, I would never have any UI coming up from Anywhere but the main thread.

所以,除了主线程,我不会有任何UI。

However, Why not simply save off the CurrentThread when you start, and compare the ThreadID with the current thread?

但是,为什么不简单地在启动时保存当前线程,并将ThreadID与当前线程进行比较?

-Chert

燧石

#1


37  

You could do it like this:

你可以这样做:

// Do this when you start your application
static int mainThreadId;

// In Main method:
mainThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;

// If called in the non main thread, will return false;
public static bool IsMainThread
{
    get { return System.Threading.Thread.CurrentThread.ManagedThreadId == mainThreadId; }
}

EDIT I realized you could do it with reflection too, here is a snippet for that:

我意识到你也可以用反射来做,这里有一个片段:

public static void CheckForMainThread()
{
    if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA &&
        !Thread.CurrentThread.IsBackground && !Thread.CurrentThread.IsThreadPoolThread && Thread.CurrentThread.IsAlive)
    {
        MethodInfo correctEntryMethod = Assembly.GetEntryAssembly().EntryPoint;
        StackTrace trace = new StackTrace();
        StackFrame[] frames = trace.GetFrames();
        for (int i = frames.Length - 1; i >= 0; i--)
        {
            MethodBase method = frames[i].GetMethod();
            if (correctEntryMethod == method)
            {
                return;
            }
        }
    }

    // throw exception, the current thread is not the main thread...
}

#2


16  

If you're using Windows Forms or WPF, you can check to see if SynchronizationContext.Current is not null.

如果您使用的是Windows窗体或WPF,您可以检查是否同步上下文。目前不是零。

The main thread will get a valid SynchronizationContext set to the current context upon startup in Windows Forms and WPF.

在Windows窗体和WPF上启动时,主线程将获得一个有效的同步上下文设置到当前上下文。

#3


10  

Here is another option:

这是另一个选择:

if (App.Current.Dispatcher.Thread == System.Threading.Thread.CurrentThread)
{
    //we're on the main thread
}

Works for me.

为我工作。

EDIT : Forgot to mention that this works only in WPF. I was searching SO for the WPF case, and I didn't notice that this question is general .NET. Another option for Windows Forms could be

编辑:忘了说这只在WPF中有效。我搜索的是WPF的例子,我没有注意到这个问题是。net的。Windows窗体的另一个选择可能是。

if (Application.OpenForms[0].InvokeRequired)
{
    //we're on the main thread
}

Of course, you should first make sure that there is at least one Form in the application.

当然,您应该首先确保应用程序中至少有一个表单。

#4


3  

Try this one if (Application.MessageLoop) . I think it is rare case to have more than 1 thread to process messages

试试这个if (Application.MessageLoop)。我认为有超过1个线程来处理消息是很少见的。

#5


2  

In my experience, if you attempt to create a dialog from another thread other than the main thread then windows gets all confused and things start going crazy. I tried to do this once with a status window to show the status of the background thread (as well as many other times someone would toss up a dialog from a background thread - and one that did have a Message Loop) - and Windows just started doing "random" things in the program. I'm pretty sure there was some unsafe handling of something going on. Had issues with clicking on the form and the wrong thread handling the messages...

根据我的经验,如果你试图从其他线程创建一个对话框,而不是主线程,那么windows就会变得混乱,事情就会变得疯狂起来。我试着做这一次的状态窗口显示后台线程的状态(以及其他许多次有人扔了一个对话框从一个后台线程,确实有一个消息循环)——和Windows只是开始做“随机”的计划。我很确定有一些不安全的处理。有问题,点击表单和错误的线程处理消息…

So, I would never have any UI coming up from Anywhere but the main thread.

所以,除了主线程,我不会有任何UI。

However, Why not simply save off the CurrentThread when you start, and compare the ThreadID with the current thread?

但是,为什么不简单地在启动时保存当前线程,并将ThreadID与当前线程进行比较?

-Chert

燧石