我知道还有其他帖子说你可以创建一个控件然后检查InvokeRequired
属性以查看当前线程是否是主线程。
问题是你无法知道该控件本身是否是在主线程上创建的。
我使用以下代码来判断一个线程是否是主线程(启动该进程的线程):
if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA ||
Thread.CurrentThread.ManagedThreadId != 1 ||
Thread.CurrentThread.IsBackground || Thread.CurrentThread.IsThreadPoolThread)
{
// not the main thread
}
有谁知道更好的方法吗?看起来这种方式在运行时的未来版本中可能容易出错或中断。
答案 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