我有一个庞大的应用程序,包括线程,定时器,调用(不是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获取了一些信息
!线程
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.
答案 0 :(得分:8)
可能是后台线程中可能出现的死锁。 尝试查看可能阻止您的应用的其他线程。
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");
答案 1 :(得分:3)
如果它冻结,你可能会看到僵局。我发现找到死锁的最好方法之一是使用崩溃转储和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
答案 2 :(得分:0)
调用很危险,很容易以意想不到的方式导致死锁,我建议替换
this.Invoke((MethodInvoker)...
带
this.BeginInvoke((MethodInvoker)...
不会阻止调用者,可能会解决问题。
编辑如果没有,你将需要等到它死锁,然后使用windbg查看你死锁的原因。
答案 3 :(得分:0)
从VS运行时,它会注入一个调试器线程,这会改变一些消息路由。对于正在等待队列中的消息的某些内容,您可能遇到Invoke(...)
阻塞问题,但在调试器下,win消息的处理顺序不同。
IIUC你不需要使用System.Windows.Forms.Timer锁,因为它使用win消息泵,所以定时器事件总是在GUI线程上处理(除非你的应用程序中的其他东西在TheadPool上运行代码或在专用背景线程。)
因此,您的示例代码中没有任何内容涉及线程,除非Web浏览器控件在后台线程上触发其事件(在这种情况下,使用BeginInvoke()
将这些事件POST回UI线程)。一旦你在主UI线程上运行所有应用程序控件,就删除锁(作为调试辅助工具)。请发布有关后台处理的更多信息以及迄今为止的任何结果。