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

时间:2010-03-03 19:51:16

标签: c# .net multithreading

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

问题是你无法知道该控件本身是否是在主线程上创建的。

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

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

有谁知道更好的方法吗?看起来这种方式在运行时的未来版本中可能容易出错或中断。

5 个答案:

答案 0 :(得分:40)

你可以这样做:

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

编辑我意识到你也可以用反射来做,这里有一段代码:

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...
}

答案 1 :(得分:17)

如果您使用的是Windows窗体或WPF,则可以检查SynchronizationContext.Current是否为空。

在Windows Forms和WPF中启动时,主线程将获得有效的SynchronizationContext设置为当前上下文。

答案 2 :(得分:12)

这是另一种选择:

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

适合我。

编辑:忘记提及这仅适用于WPF。我正在搜索WPF案例,我没有注意到这个问题是一般的.NET。 Windows Forms的另一个选项可能是

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

当然,您应首先确保应用程序中至少有一个Form

答案 3 :(得分:3)

这要容易得多

static class Program
{
  [ThreadStatic]
  public static readonly bool IsMainThread = true;

//...
}

您可以在任何线程中使用它:

if(Program.IsMainThread) ...

答案 4 :(得分:2)

根据我的经验,如果你试图从主线程以外的另一个线程创建一个对话框,那么windows会让所有人感到困惑,事情就会变得疯狂。我尝试用状态窗口执行此操作一次以显示后台线程的状态(以及其他许多时候有人会从后台线程中抛出一个对话框 - 还有一个确实有一个消息循环) - 而Windows刚刚启动在程序中做“随机”的事情。我很确定对某些事情有一些不安全的处理。有点击表单的问题和处理消息的错误线程...

所以,除了主线程之外,我永远不会有任何来自任何地方的用户界面。

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

-Chert