如何判断一个线程是否是C#中的主线程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2374451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to tell if a thread is the main thread in C#
提问by jjxtra
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.
有人知道更好的方法吗?似乎这种方式在运行时的未来版本中可能容易出错或中断。
采纳答案by Zach Johnson
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; }
}
EDITI 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...
}
回答by Reed Copsey
If you're using Windows Forms or WPF, you can check to see if SynchronizationContext.Currentis not null.
如果您使用的是 Windows 窗体或 WPF,您可以检查SynchronizationContext.Current是否不为空。
The main thread will get a valid SynchronizationContextset to the current context upon startup in Windows Forms and WPF.
在 Windows 窗体和 WPF 中启动时,主线程将获得设置为当前上下文的有效SynchronizationContext。
回答by Chert Pellett
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?
但是,为什么不在启动时简单地保存 CurrentThread,并将 ThreadID 与当前线程进行比较?
-Chert
-燧石
回答by cheesus
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.
当然,您首先应该确保Form
应用程序中至少有一个。
回答by Christian Ohle
It is much more easy:
这要容易得多:
static class Program
{
[ThreadStatic]
public static readonly bool IsMainThread = true;
//...
}
And you can use it from any thread:
您可以从任何线程使用它:
if(Program.IsMainThread) ...