C# 应用程序在Visual Studio外部冻结。从VisualStudio启动时,它可以正常工作

C# 应用程序在Visual Studio外部冻结。从VisualStudio启动时,它可以正常工作,c#,visual-studio-2010,visual-studio-2008,freeze,C#,Visual Studio 2010,Visual Studio 2008,Freeze,慢慢地,我工作过度了 我有一个包含线程、计时器、调用(不是BeginInvoke,所以它是同步的)和application.DoEvents的大型应用程序 在这里发布太多了,我不知道问题到底出在哪里 我的每一种方法都是一种尝试。每一次捕获都被记录下来 如果我从VisualStudio(F5)启动应用程序,或者通过Ants对其进行分析,那么就没有问题。应用程序从几天后开始运行。 但只要我通过windows资源管理器启动相同的调试版本,它就会每隔几个小时冻结一次。它毫无例外地冻结了。 如果我将vis

慢慢地,我工作过度了

我有一个包含线程、计时器、调用(不是BeginInvoke,所以它是同步的)和application.DoEvents的大型应用程序

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

我的每一种方法都是一种尝试。每一次捕获都被记录下来

如果我从VisualStudio(F5)启动应用程序,或者通过Ants对其进行分析,那么就没有问题。应用程序从几天后开始运行。 但只要我通过windows资源管理器启动相同的调试版本,它就会每隔几个小时冻结一次。它毫无例外地冻结了。 如果我将visual studio附加到此应用程序并断开它,它将在application.Run(new Form1())上停止

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

它是一个.NET3.5WinForms应用程序

这里好像挂着一根线:

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

DoEvents()的示例。这在lock()和invoke中

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");
    }
}
!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.

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

Toolbar -> Debug -> Windows -> Threads

应该有多个线程,如果你双击其中一个,你会看到它停止你的应用程序的那一行

Toolbar -> Debug -> Windows -> Threads
如果您在代码中输入这一行:

Control.CheckForIllegalCrossThreadCalls = false;
再次将其设置为true。死锁的一个可能原因是后台线程访问控件

而不是从一个后台线程写这篇文章

button1.Text = "hello"
写这个

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

如果天气很冷,你很可能会陷入僵局。我发现找到死锁的最好方法之一是使用崩溃转储和sosex

下面是一篇关于使用这种技术的好文章(它是asp.net,但同样的原则也适用):


让应用程序一直运行到冻结,然后进行挂起转储:

调用是危险的,很容易以我建议的意外方式造成死锁

this.Invoke((MethodInvoker).

this.BeginInvoke((MethodInvoker).

这不会阻止来电者,可能会解决问题


如果没有,请编辑。您将需要等待它死锁,然后使用windbg查看死锁的原因。

从VS运行时,它将插入一个调试器线程,这将更改一些消息路由。您的
调用(…)可能有问题
阻塞队列中等待消息的内容,但在调试器下,win消息的处理顺序不同

IIUC System.Windows.Forms.Timer不需要锁定,因为它使用win消息泵,所以计时器事件始终在GUI线程上处理(除非应用程序中的其他部分在ADPool或专用后台线程中运行代码)


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

您手头上有一个死锁。尽管这些很难诊断。可能是内存泄漏导致内存不足,是的,可能与zmbq相同。从IDE运行它会大大降低速度,因此并发锁定的可能性更小。它使用grabber.invokererequired但使用this.Invoke()没有意义。在允许窗体关闭之前,请始终确保线程已结束,计时器已禁用,所有经过的调用均已耗尽。并且绝对不要使用计时器。计时器在10秒的间隔内,Winforms计时器也会正常工作,不会给您带来同步痛苦。您如何使用Application.DoEvents?这对我来说是红色的flag.Thank。通过这些线程,我找到了我主要问题的编辑部分,您可以尝试使用
BeginInvoke
而不是
Invoke
,它不会等待调用返回,但我会使用
System.Windows.Forms.Timer
,您正在Windows窗体上下文中使用此代码,对吗?Windows窗体计时器勾号事件会触发在GUI线程中,因此您不必担心同步。目前我使用System.Windows.Forms.Timer和一些锁,但没有改进。
this.Invoke(() => button1.Text = "hello");