应用程序在 Visual Studio 之外冻结.从Visual Studio启动它时,它可以工作

本文关键字:Visual Studio 工作 冻结 应用程序 启动 | 更新日期: 2023-09-27 18:36:14

慢慢地我过度劳累了...

我有一个巨大的应用程序,包括线程,计时器,调用(不是BeginInvoke,所以它是同步的)和Application.DoEvents。

在这里发布太多了,我不知道问题到底在哪里。

我的每一种方法都在尝试捕获中。每个渔获都被记录下来。

如果我从Visual Studio (F5)启动我的应用程序,或者在通过Ants分析它时,则没有问题。应用程序从几天开始运行。但是一旦我通过 Windows 资源管理器启动相同的调试版本,它每隔几个小时就会冻结一次。它无一例外地冻结。如果我将Visual Studio附加到此应用程序并破坏它,它将在Application.Run(new Form1())上停止;

我真的很困惑,不知道修复它。

这是一个.net 3.5 winforms应用程序

看起来一个线程挂在这里:

if (grabber.InvokeRequired)
{
    Console.WriteLine("grabber.InvokeRequired");
    this.Invoke((MethodInvoker) delegate { grabber.Navigate("http://www.google.de"); }); // <-- hang
}
else
{
    grabber.Navigate(ig.StartUrl);
}

此代码段是计时器事件的一部分

_timeout = new System.Timers.Timer(10000);
_timeout.Elapsed += new ElapsedEventHandler(OnWatchDogBark);

编辑

DoEvents() 的示例。这是在 lock() 和调用中

grabber.DocumentCompleted -= grabber_DocumentCompleted;
grabber.Navigate("http://www.google.de");
while (grabber.ReadyState != WebBrowserReadyState.Complete)
{
    timeout--;
    Application.DoEvents();
    Thread.Sleep(200);
    if (timeout < 0)
    {
        timeout = 50;
        grabber.Navigate("http://www.google.de");
    }
}

目前我使用System.Windows.Forms.Timer和一些锁,但没有改进。

好的,我使用 WinDbg 获取一些信息

编辑: 14.06.2012

!线程

                                      PreEmptive   GC Alloc           Lock
       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception
   0    1 37ec 007cab18      6020 Enabled  00000000:00000000 007c8510     0 STA System.ArgumentException (02762ba8)
   2    2 85b8 007d7c38      b220 Enabled  00000000:00000000 007c8510     0 MTA (Finalizer)
XXXX    3    0 06e9f548      9820 Enabled  00000000:00000000 007c8510     0 Ukn
  21    5 3464 0d6dc598   200b020 Enabled  28cb5820:28cb5fe8 007c8510     0 MTA
  22    6 62b0 0d6db9e0   200b220 Enabled  00000000:00000000 007c8510     0 MTA
  23    7 8e58 0d6db5f8    80a220 Enabled  00000000:00000000 007c8510     0 MTA (Threadpool Completion Port)
XXXX    4    0 06f62d40   1801820 Enabled  00000000:00000000 007c8510     0 Ukn (Threadpool Worker)
XXXX    f    0 132a3290   1801820 Enabled  00000000:00000000 007c8510     0 Ukn (Threadpool Worker)
XXXX   10    0 132a3678   1801820 Enabled  00000000:00000000 007c8510     0 Ukn (Threadpool Worker)
XXXX    e    0 132a26d8   1801820 Enabled  00000000:00000000 007c8510     0 Ukn (Threadpool Worker)
XXXX    9    0 0d6db210   1801820 Enabled  00000000:00000000 007c8510     0 Ukn (Threadpool Worker)

!dlk

Examining SyncBlocks...
Scanning for ReaderWriterLock instances...
Scanning for holders of ReaderWriterLock locks...
Scanning for ReaderWriterLockSlim instances...
Scanning for holders of ReaderWriterLockSlim locks...
Examining CriticalSections...
Could not find symbol ntdll!RtlCriticalSectionList.
No deadlocks detected.

应用程序在 Visual Studio 之外冻结.从Visual Studio启动它时,它可以工作

可能是

后台线程中的死锁。尝试查看可能阻止您的应用的其他线程。

Toolbar -> Debug -> Windows -> Threads

http://msdn.microsoft.com/en-us/library/w15yf86f.aspx

应该有多个线程,如果双击一个线程,您会看到它停止应用程序的行。

如果你在代码中的这一行:

Control.CheckForIllegalCrossThreadCalls = false;

再次将其设置为 true。死锁的可能原因是后台线程访问控制。

而不是从背景线程中写这个。

button1.Text = "hello"

写这个。

this.Invoke(() => button1.Text = "hello");

如果它冻结,您可能会看到死锁。 我发现找到死锁的最好方法之一是使用崩溃转储和 sosex。

这里有一篇关于使用这种技术的好文章(它 asp.net,但同样的原则适用): http://blogs.msdn.com/b/tess/archive/2010/04/27/debugging-a-classic-readerwriterlock-deadlock-with-sosex-dll.aspx

让应用程序运行直到冻结,然后进行挂起转储:http://blogs.msdn.com/b/tess/archive/2006/10/16/net-hang-debugging-walkthrough.aspx

调用很危险,很容易以意想不到的方式导致死锁,我建议替换

this.Invoke((MethodInvoker)...

this.BeginInvoke((MethodInvoker)...

这不会阻止调用方,并且可能会解决问题。

编辑 如果没有,

您需要等到它死锁,然后使用 WindBG 查看您死锁的原因。

从 VS 运行时,它将注入一个调试器线程,这会更改一些消息路由。 在队列中等待消息的内容上,Invoke(...)阻塞可能会遇到问题,但在调试器下,获胜消息以不同的顺序处理。

IIUC 你不需要使用 System.Windows.Forms.Timer 锁,因为它使用 win 消息泵,因此计时器事件始终在 GUI 线程上处理(除非应用中的其他内容在 TheadPool 或专用后台线程中运行代码)。

因此,示例代码中的任何内容都不涉及线程,除非 Web 浏览器控件在后台线程上触发其事件(在这种情况下,使用 BeginInvoke() 将这些事件发布回 UI 线程)。 在主 UI 线程上运行所有应用程序控件后,删除锁(作为调试辅助)。 请发布有关后台处理和迄今为止的任何结果的更多信息。