我的C# WinForms应用程序为什么会冻结/挂起?

4
我有一个.Net 2.0 C# WinForms应用程序,在开发中运行良好,但在生产环境中偶尔会出现冻结。我已经寻找了所有常见的罪魁祸首:
1.我使用了InvokeRequired和Invoke来确保没有UI组件从错误的线程进行操作。
2.我在UI线程上同步了所有计时器对象。
3.我阅读了这篇文章http://www.ikriv.com/en/prog/info/dotnet/MysteriousHang.html关于OnUserPreferenceChanged,我确实遇到了这个问题,但我修复了它。

这是当我们从.Net 1.1迁移到.Net 2+后开始发生的。在此之前,它从未出现过卡顿。

当这个问题发生时,我使用Managed Stack Explorer定期从生产应用程序获取堆栈跟踪,主UI线程总是卡在一些新的随机位置。如果这是线程死锁,它不会被WaitOne阻塞,这并不像您所期望的那样。

我的应用程序执行以下操作:
- 使用多个System.Timers.Timer实例。
- 使用WMI来管理打印。
- 有一些后台线程对服务器进行Web服务调用,但不与UI交互。
- 有一些后台线程使用System.Diagnostics.Process查看计算机上的其他进程,并有时将其关闭。
- 与使用串口与钞票接受器通信的第三方dll进行交互。
- 与一些com / activex / ocx控件进行交互,以与信用卡读卡器进行交互。

这是一个它挂起并且所有堆栈跟踪的示例:

Thread ID: 2816  
    0. System.Threading.WaitHandle.WaitOne (Source Unavailable)
    1. System.Threading.WaitHandle.WaitOne (Source Unavailable)
    2. System.Threading.WaitHandle.WaitOne (Source Unavailable)
    3. System.Management.MTAHelper.WorkerThread (Source Unavailable)
    4. System.Threading.ThreadHelper.ThreadStart_Context (Source Unavailable)
    5. System.Threading.ExecutionContext.Run (Source Unavailable)
    6. System.Threading.ThreadHelper.ThreadStart (Source Unavailable)

Thread ID: 2828  

Thread ID: 2852  
    0. MeiNet.EBDS.BillAcceptor.submitRequestStack (Source Unavailable)
    1. MeiNet.EBDS.BillAcceptor.OnHandleEscrowed (Source Unavailable)
    2. MeiNet.EBDS.BillAcceptor.EventHandler (Source Unavailable)

Thread ID: 2908  

Thread ID: 2820  
    0. System.Threading.Thread.Sleep (Source Unavailable)
    1. MyApp.ProcessKiller.startSpecialKillerLoop (ProcessKiller.cs:115)
    2. System.Threading.ThreadHelper.ThreadStart_Context (Source Unavailable)
    3. System.Threading.ExecutionContext.Run (Source Unavailable)
    4. System.Threading.ThreadHelper.ThreadStart (Source Unavailable)

Thread ID: 2600  

Thread ID: 2844  
    0. System.Threading.Thread.Start (Source Unavailable)
    1. System.Net.TimerThread.Prod (Source Unavailable)
    2. System.Net.TimerThread.TimerQueue.CreateTimer (Source Unavailable)
    3. System.Net.ServicePoint..ctor (Source Unavailable)
    4. System.Net.ServicePointManager.FindServicePointHelper (Source Unavailable)
    5. System.Net.ServicePointManager.FindServicePoint (Source Unavailable)
    6. System.Net.HttpWebRequest.FindServicePoint (Source Unavailable)
    7. System.Net.HttpWebRequest.GetRequestStream (Source Unavailable)
    8. System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke (Source Unavailable)
    9. MyApp.MyServer.Server.hb4 (Reference.cs:588)
    10. MyApp.HeartbeatSender.SendThreadedHeartbeat (HeartbeatSender.cs:81)
    11. MyApp.HeartbeatSender.StartHeartbeatLoop (HeartbeatSender.cs:40)
    12. System.Threading.ThreadHelper.ThreadStart_Context (Source Unavailable)
    13. System.Threading.ExecutionContext.Run (Source Unavailable)
    14. System.Threading.ThreadHelper.ThreadStart (Source Unavailable)

Thread ID: 2824  
    0. System.Threading.Thread.Sleep (Source Unavailable)
    1. MyApp.OfficeMonitor.StartMonitoring (OfficeMonitor.cs:84)
    2. System.Threading.ThreadHelper.ThreadStart_Context (Source Unavailable)
    3. System.Threading.ExecutionContext.Run (Source Unavailable)
    4. System.Threading.ThreadHelper.ThreadStart (Source Unavailable)

Thread ID: 2584  
    0. [Internal thisFrame, 'M-->U', System.Windows.Forms.UnsafeNativeMethods::GetModuleHandle] (Source Unavailable)
    1. System.Windows.Forms.Application.get_ComCtlSupportsVisualStyles (Source Unavailable)
    2. System.Windows.Forms.ButtonInternal.ButtonStandardAdapter.PaintWorker (Source Unavailable)
    3. System.Windows.Forms.ButtonInternal.ButtonStandardAdapter.PaintUp (Source Unavailable)
    4. System.Windows.Forms.ButtonInternal.ButtonStandardAdapter.PaintOver (Source Unavailable)
    5. System.Windows.Forms.ButtonInternal.ButtonBaseAdapter.Paint (Source Unavailable)
    6. System.Windows.Forms.ButtonBase.OnPaint (Source Unavailable)
    7. System.Windows.Forms.Control.PaintWithErrorHandling (Source Unavailable)
    8. System.Windows.Forms.Control.WmPaint (Source Unavailable)
    9. System.Windows.Forms.Control.WndProc (Source Unavailable)
    10. System.Windows.Forms.ButtonBase.WndProc (Source Unavailable)
    11. System.Windows.Forms.Button.WndProc (Source Unavailable)
    12. System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Source Unavailable)
    13. System.Windows.Forms.Control.ControlNativeWindow.WndProc (Source Unavailable)
    14. System.Windows.Forms.NativeWindow.Callback (Source Unavailable)
    15. [Internal thisFrame, 'M-->U', System.Windows.Forms.SafeNativeMethods::UpdateWindow] (Source Unavailable)
    16. System.Windows.Forms.Control.Update (Source Unavailable)
    17. System.Windows.Forms.Control.Refresh (Source Unavailable)
    18. MyApp.MainForm.ClearFields (MainForm.cs:4057)
    19. MyApp.MainForm.ShowHomeButtons (MainForm.cs:5664)
    20. MyApp.MainForm.ShowScreenSaver (MainForm.cs:4284)
    21. MyApp.MainForm.ScreensaverTimerTick (MainForm.cs:7817)
    22. System.RuntimeMethodHandle.InvokeMethodFast (Source Unavailable)
    23. System.Reflection.RuntimeMethodInfo.Invoke (Source Unavailable)
    24. System.Delegate.DynamicInvokeImpl (Source Unavailable)
    25. System.Windows.Forms.Control.InvokeMarshaledCallbackDo (Source Unavailable)
    26. System.Windows.Forms.Control.InvokeMarshaledCallbackHelper (Source Unavailable)
    27. System.Threading.ExecutionContext.runTryCode (Source Unavailable)
    28. System.Threading.ExecutionContext.RunInternal (Source Unavailable)
    29. System.Threading.ExecutionContext.Run (Source Unavailable)
    30. System.Windows.Forms.Control.InvokeMarshaledCallback (Source Unavailable)
    31. System.Windows.Forms.Control.InvokeMarshaledCallbacks (Source Unavailable)
    32. System.Windows.Forms.Control.WndProc (Source Unavailable)
    33. System.Windows.Forms.ScrollableControl.WndProc (Source Unavailable)
    34. System.Windows.Forms.ContainerControl.WndProc (Source Unavailable)
    35. System.Windows.Forms.Form.WndProc (Source Unavailable)
    36. System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Source Unavailable)
    37. System.Windows.Forms.Control.ControlNativeWindow.WndProc (Source Unavailable)
    38. System.Windows.Forms.NativeWindow.Callback (Source Unavailable)
    39. [Internal thisFrame, 'M-->U', System.Windows.Forms.UnsafeNativeMethods::DispatchMessageW] (Source Unavailable)
    40. System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop (Source Unavailable)
    41. System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (Source Unavailable)
    42. System.Windows.Forms.Application.ThreadContext.RunMessageLoop (Source Unavailable)
    43. System.Windows.Forms.Application.Run (Source Unavailable)
    44. MyApp.MainForm.Main (MainForm.cs:2975)

你有什么建议我应该做什么吗?


你所说的“hang”是指用户界面不再响应了吗?还是有错误信息显示出来? - CodingBarfield
1
@Nobody 我认为没有人能够在不看到所有代码的情况下为你的应用程序卡顿提供任何具体建议(这超出了SO的范围)。 - msarchet
1
死锁不仅发生在你让某个东西等待的时候。如果你正在锁定某个东西,而另一个线程试图锁定它,这可能会导致死锁;如果一个方法依赖于尚未初始化的某些内容并且需要锁定,那么也可能会导致死锁等等。使用线程时一定要非常小心。 - Chris Pfohl
没有错误信息。用户界面只是变得无响应。 - Category6
我应该补充说明,在我们从 .Net 1.1 迁移到 .Net 2+ 后,这个问题开始出现。在那之前从未发生过。 - Category6
显示剩余2条评论
3个回答

2

一些想法:

  • 您的开发环境中是否使用了在生产环境中不存在的预处理器标志?所以任何#If Debug或其他。

  • 您是否在发布模式下测试了开发环境?它仍然不会挂起吗?

  • 机器有什么不同?其中一个有更多的RAM,四核对双核,一个在百万防火墙后面而另一个没有?

  • 在您的线程中,您确定没有任何东西在等待某个回调完成后才更新UI元素吗?

  • 您是否使用数据库?如果是这样,它们是否不同,它们之间有什么不同?

  • 挂起可能是由于您正在提取StackTraces引起的吗?

  • 您是否在任何地方吞咽异常,这些异常可能告诉您发生了什么?

  • 机器上的串口有什么不同吗?

  • 是否使用相同的账单接收器?

继续等等。

尝试在新的虚拟机上安装并查看会发生什么。这可能是一些旧的dll或驱动程序,大多数时候,当出现“在我的机器上工作”的症状时,是因为您做了一些您忘记了的事情,使事情正常工作。


感谢您的建议。快速回答:没有标志,没有不同的模式,我会检查硬件,没有线程正在等待回调,没有数据库,直到出现这个问题之前才开始获取堆栈跟踪,记录所有异常,我会检查串口,我们将检查接收器。再次感谢您对此的关注。 - Category6

1
我们遇到了完全相同的问题,而这篇文章(就像你提到的那样)指引我们找到了解决方案: http://www.ikriv.com/dev/dotnet/MysteriousHang.html#WhatToDo 我们使用了以下代码的启动画面:
ThreadPool.QueueUserWorkItem((x) =>
{
    using (var splashForm = new SplashForm())
    {
        splashForm.Show();
        while (!done)
            Application.DoEvents();
        splashForm.Close();
    }
});

我们很幸运地复现了死锁。我们有一台笔记本电脑/平板电脑,您可以将屏幕从键盘上拆下来,这样您就只有一个平板电脑。每次我们拆下屏幕时,我们的应用程序都会挂起。在去除闪屏后,我们的问题解决了。
顺便说一下,我们遇到了完全相同的堆栈跟踪问题。
System.Threading.WaitHandle.WaitOne (Source Unavailable)
1. System.Threading.WaitHandle.WaitOne (Source Unavailable)
2. System.Threading.WaitHandle.WaitOne (Source Unavailable)
3. System.Management.MTAHelper.WorkerThread (Source Unavailable)
4. System.Threading.ThreadHelper.ThreadStart_Context (Source Unavailable)
5. System.Threading.ExecutionContext.Run (Source Unavailable)
6. System.Threading.ThreadHelper.ThreadStart (Source Unavailable)

当然,我不知道你的问题是否有相同的原因/解决方案...但这对我们有效。


0

我曾经遇到过一个类似的问题,其中一个线程在调用Application.get_ComCtlSupportsVisualStyles时出现了问题。

我想知道您是否启用了视觉样式? http://ryanfarley.com/blog/archive/2004/05/05/599.aspx 描述了如何使用代码或清单文件来实现。 (我认为清单文件是首选解决方案。)

如果您启用了视觉样式,并且假设操作系统支持主题(我认为此功能始于XP),则Application.get_ComCtlSupportsVisualStyles不必做太多工作,可以快速返回true。

话虽如此,我仍然不明白为什么调用GetModuleHandle()会挂起。 我在网上找到的大部分内容都表明这将是LoadLibrary()期间的问题,而不是.NET Win Forms绘图事件期间的问题。 我不知道是否可能有另一个线程同时在LoadLibrary()中执行不安全的工作...?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接