我如何获得winform的GUI线程?

我有一个带有多个GUI线程的winforms应用程序。 我希望他们能够访问彼此的线程对象,而无需单独跟踪这些信息。

.NET中是否有一个函数可以提供winforms控件或窗口对象,然后返回线程? 或者API中的一个函数我可以为threadID设置pinv?

(请不要发表评论说我应该采取另一种方式……这也不是关于跨线程窗口操作。)

谢谢!

编辑

对于那些由于某种原因相信我的斜体文字,祝贺你的人你被录用了!! 这是问题所在:

“应用程序通过完全锁定在野外崩溃,也就是说,它停止响应。非常间歇性,并试图调试它,似乎永远不会发生。”

那怎么办? 在程序中安装一个选项,用户可以在我们的指导下激活,从同一应用程序中的另一个GUI线程,在主GUI线程上执行thread.abort,然后我们可以在错误日志中查看调用堆栈。 Viola,在不到一天的时间内发现无法调试错误。 (现在停止,它与滥用multithreading无关:-)

我承认我几乎没有问这个,我做的原因是我可以看到主要表单的对象引用,但是没有任何针对它的线程。 我给Chris Shain答案a / c这是一个快速的方法,不幸的是当线程挂起时,我将无法进行调用(它也会挂起)。 更多挖掘揭示了GetWindowThreadProcessId API调用。 但它是一个非托管的线程ID,显然有并发症将其转化为托管线程ID。

所以我咬了一下子弹,并对主UI线程进行了全局引用。 本来会发布它,但尚未写出来。

现在,如果你原谅VB ……

在主公共模块/静态类中:

Public GUIThread As Threading.Thread Sub Main() '' // Create app main window ShellForm = New frmShell '' // Save main GUI Thread for abort routine GUIThread = Threading.Thread.CurrentThread If GetSetting("MyApp", "Testing", "CrashDebug", "False") = "True" Then '' // DO NOT run the pgm. like this normally - with try/catch around '' // Application.Run - or uncaught errors will kill the whole app!!! Try '' // This is the other of the 'Multiple GUI threads' I talked '' // about in the Orig Post. Dim t As New Threading.Thread(AddressOf StartCrashDebug) t.Start() Application.Run(ShellForm) Catch ex As Exception '' // This error routine passes errors off to another thread which '' // logs them (and also shows messages) MyLogError(ex, "CrashDebug - Main Window blew up") End Try Else '' // Normal mode - uncaught errors will get caught by UnhandledException, '' // logged, and Winforms will keep the GUI alive (since we _do_ care '' // more about users than computers right ;-) Application.Run(ShellForm) End If End Sub Sub StartCrashDebug() Dim f As New frmCrashFinder '' // Starting a window like this on a separate thread makes it 'Another '' // GUI thread' for winforms, by design Application.Run(f) End Sub 

在’aborter’WinForm中:

 Public Class frmCrashFinder Inherits Windows.Form Private Sub Abort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Abort.Click GUIThread.Abort() End Sub End Class 

这应该这样做,但我同意其他海报,这可能是出于其他原因做错的事情……

 var thatWindowsThread = (Thread)(WhateverWindow.Invoke(()=>Thread.CurrentThread); 

Windows窗体中的所有GUI元素通常在单个线程上完成。 我强烈建议避免尝试以任何其他方式执行此操作。

您可以使用Control.Invoke或Control.BeginInvoke与任何Control一起编组代码到该线程。

如果你真的想得到线程的ID(不知道这将是什么用途??),你可以使用:

 int GetControlThreadId(Control control) { int threadId; control.Invoke( new Action( () => { threadId = Thread.CurrentThread.ManagedThreadId; })); return threadId; } 

如果您的代码不在表单或控件中,则可以使用

 if (System.Windows.Forms.Form.ActiveForm.InvokeRequired) { System.Windows.Forms.Form.ActiveForm.Invoke(...); } 

WindowsFormsSynchronizationContext.Current具有PostSend方法,您可以从中将命令委派给UI线程