问题描述
我有多个线程GUI一个WinForms应用程序。我希望他们能够访问对方的线程对象,而无需跟踪的信息分开。
有没有在.NET中一个功能,我可以养活一个WinForms控制或窗口对象,并取回线程?或API的功能,我可以的PInvoke为主题ID?
的(请没有评论说我应该做的另一种方式......也这是不是跨线程窗口操作。)的
谢谢!
修改
对于那些你谁出于某种原因认为我的斜体,congratualations,你聘请了!这里的问题是:
应用程序在崩溃狂热的完全锁定,也就是说,它会停止响应。非常间歇性,并试图调试它,它似乎永远不会发生。
那么什么呢?安装在用户可以在我们的方向激活程序的选项,即在同一应用程序的另一个GUI线程,做一个Thread.Abort的主界面线程,那么我们可以看看在错误日志中调用堆栈。中提琴,发现了一个不可能调试错误在不到一天的时间。 (现在停下来,它有无关滥用多线程:-)
我承认我差点没问这个,我做的原因是我能看到一个对象引用的主要形式,但没有任何它的线程。我给克里斯·沙恩答案的A / C是一种快速的方法,可惜的是,当线程挂起,我不能够做一个invoke(它会挂起太)。更多的有一点点的GetWindowThreadProcessId API调用。但它是一个非托管线程ID,显然有并发症转向了到托管线程ID。
于是我咬了子弹,把在全球参照主UI线程。本来贴吧开始,但还没有写呢。
现在,如果你原谅我的VB ...
在主要公共模块/静态类:
公共GUIThread作为Threading.Thread
子主()
''//创建应用程序的主窗口
ShellForm =新frmShell
''//保存主界面线程的异常结束程序
GUIThread = Threading.Thread.CurrentThread
。如果GetSetting(MyApp的,测试,CRASHDEBUG,假)=真然后
''//不运行铂族金属。像这样的正常 - 周围
''// Application.Run的try / catch - 或未被捕获的错误会杀死整个应用程序!
尝试
''//这是其他的多线程的GUI我跟
''//有关在原稿后。
尺寸T作为新Threading.Thread(AddressOf StartCrashDebug)
t.Start()
Application.Run(ShellForm)
抓住EX作为例外
''//这个错误例程传递错误关闭到
另一个线程''//记录它们(也说明消息)
MyLogError(例如,CRASHDEBUG - 主窗口炸毁)
端尝试
,否则
''//正常模式 - 未被捕获的错误会被UnhandledException被抓住,
''//记录,和WinForms将保持GUI活着(因为我们_do_护理
''//更多的用户比电脑右;-)
Application.Run(ShellForm)
端如果
端子
子StartCrashDebug()
昏暗f,按新frmCrashFinder
''//在单独的线程启动这样一个窗口,使得它的另一个
''// GUI线程'为的WinForms,设计
Application.Run( F)
端子
在'中止器的WinForm:
公共类frmCrashFinder
继承Windows.Form
私人小组Abort_Click(BYVAL发件人为System.Object的,BYVAL E上System.EventArgs)把手Abort.Click
GUIThread.Abort()
端子
端类
这应该这样做,但是我与其他海报同意,这可能是错误的事情其他原因做...
VAR thatWindowsThread =(螺纹)(WhateverWindow.Invoke(()=> Thread.CurrentThread);
I have a winforms app with multiple GUI threads. I want them to be able to access each other's thread objects without having to keep track of that information separately.
Is there a function in .NET that I can feed a winforms control or window object, and get back the thread? Or a function in the API I can pinvoke for the threadID?
(please no comments saying I should do it another way... also this is not about cross-thread window operations.)
Thanks!
Edit
For those of you who for some reason believed my italicized text, congratualations, you're hired!! Here is the problem:
"App is crashing in the wild by locking up totally, that is, it stop responding. Very intermittent, and trying to debug it, it seems to never happen."
So what do do? Install an option in the program that the user can activate under our direction, whereby from another GUI thread in the same app, do a thread.abort on the main GUI thread, then we can look at the call stack in the error log. Viola, found an impossible to debug error in less than a day. (Stop now, it had nothing to do with abusing multithreading:-)
I'll admit I almost didn't ask this, the reason I did was I could see an object reference to the main form, but there wasn't any for its thread. I'm giving Chris Shain the answer a/c it is a quick way, unfortunately when the thread is hanging, I wouldn't be able to do an invoke (it would hang too). A little more digging revealed the GetWindowThreadProcessId API call. But it's an unmanaged thread ID, apparently there are complications turning that into a managed thread ID.
So I bit the bullet and put in a global reference to the main UI thread. Would have posted it to begin with, but hadn't written it yet.
Now if you'll pardon the VB...
In main public module/static class:
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
In ‘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
This should do it, however I agree with other posters that this is probably the wrong thing to do for other reasons...
var thatWindowsThread = (Thread)(WhateverWindow.Invoke(()=>Thread.CurrentThread);
这篇关于我如何获得的winform的GUI线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!