【发布时间】:2011-02-01 19:12:12
【问题描述】:
我有一个带有多个 GUI 线程的 winforms 应用程序。我希望他们能够访问彼此的线程对象,而不必单独跟踪该信息。
.NET 中是否有一个函数可以提供一个 winforms 控件或窗口对象,然后取回线程?或者API中的一个函数我可以为threadID调用?
(请不要让 cmets 说我应该以另一种方式来做......这也与跨线程窗口操作无关。)
谢谢!
编辑
对于那些出于某种原因相信我的斜体文字的人,恭喜你,你被录用了!问题是:
“应用程序因完全锁定而在野外崩溃,即停止响应。非常断断续续,尝试调试它似乎永远不会发生。”
那该怎么办?在程序中安装一个选项,用户可以在我们的指导下激活,从而从同一个应用程序中的另一个 GUI 线程,在主 GUI 线程上执行 thread.abort,然后我们可以查看错误日志中的调用堆栈。 Viola,不到一天就发现了一个无法调试的错误。 (停止,这与滥用多线程无关:-)
我承认我几乎没有问这个,我这样做的原因是我可以看到对主窗体的对象引用,但它的线程没有任何引用。我正在给 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
在“终止”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
【问题讨论】:
-
请不要让 cmets 说我应该用另一种方法来做 对,因为你的方法是解决问题的唯一可能方法。不要假设没有人能想出比你已经拥有的更好的主意。
-
这没有意义,线程不“拥有”一个对象。
-
请注意,您的问题标题与您在问题正文中实际询问的内容不一致。
-
@Ed S.(作为记录,他在我添加编辑之前说过这个)...如果我能找到一个更好的解决方案来解决这个特殊问题,我会很高兴!当然,我也不认为这真的会奏效!
-
@stakx,@Hans Passant,为糟糕的描述道歉;我的英语成绩很差。
从 Main() 线程执行 application.run(winform1);启动执行 application.run(winform2) 的 thread2。 mainthread 是第一个 GUI 线程,“属于”(或反之亦然)winform1 和该线程创建的任何其他窗口; thread2 和 winform2 也是如此。