11

slowly I'm overworked...

I have a huge application with threading, timers, invoke (not BeginInvoke, so it is synchronous) and Application.DoEvents.

It is too much to post here and I don't know where the problem really is.

Every Method of mine is inside a try catch. Every catch is logged.

If I start my application from Visual Studio (F5) or while profiling it via Ants there is no Problem. The Application runs since some days. But as soon as I start the same debug version via windows explorer it freezes every few hours. It freezes without any exception or so. If I attach visual studio to this application and break it, it stops on Application.Run(new Form1());

I'm really confused and have no idea to repair it.

It is a .net 3.5 winforms application

It looks like one thread hangs here:

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

this snippet is part of an timer event

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

Edit

A sample for DoEvents(). This is in a lock() and in an 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");
    }
}

Currently I use the System.Windows.Forms.Timer and some locks but there is no improvement.

Okay I used WinDbg to get some informations

Edit: 14.06.2012

!threads

                                      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.
CharithJ
  • 46,289
  • 20
  • 116
  • 131
masterchris_99
  • 2,683
  • 7
  • 34
  • 55
  • 1
    You have a deadlock on your hands. These are hard to diagnose, though. – zmbq Jun 05 '12 at 09:34
  • may be memory leaks making it run out of memory [memory leak in c sharp](http://stackoverflow.com/questions/620733/memory-leak-in-c-sharp) , [how-to-detect-memory-leaks in-c-sharp-application](http://stackoverflow.com/questions/2259433/how-to-detect-memory-leaks-in-c-sharp-application)? – PresleyDias Jun 05 '12 at 09:37
  • Yup, would say the same as zmbq. Running it from the IDE slows it down tremendously so locks from concurrency are just less likely to occur. – Christoph Grimmer Jun 05 '12 at 09:38
  • It makes no sense to use grabber.InvokeRequired but then use this.Invoke(). Always make sure that threads have ended, timers are disabled and all Elapsed invocations have drained before allowing a form to close. And definitely don't use Timers.Timer for a 10 second interval, a Winforms timer will work just as well and won't give you the synchronization misery. – Hans Passant Jun 05 '12 at 11:50
  • 2
    How do you use Application.DoEvents? This, to me is a red flag. – Chris Dunaway Jun 05 '12 at 18:01
  • I have added the doEvents part – masterchris_99 Jun 06 '12 at 07:11
  • I would avoid DoEvents -- it looks like you could just as easily have a background thread performing that check (check grabber.readystate and call grabber.navigate on an invoke if necessary). Reentrancy problems caused by DoEvents can be just as hairy to debug and get right as using threading. Also, bear in mind that a lock won't protect against DoEvents reentrancy because the reentrant code called by DoEvents is potentially running on the same thread that is holding the lock. – JMarsch Jun 07 '12 at 15:28
  • Definitely a dead lock. Had encountered a few my self when using DoEvents. Check the complete call stack of all threads and post what you see as suspicious – Sandeep Singh Rawat Jun 11 '12 at 21:56
  • I have added the Deadlock Monitor and the Timedlock-Class without any success... :-( – masterchris_99 Jun 14 '12 at 05:39

4 Answers4

8

Could be a possible Deadlock in a background thread. Try looking at other threads that could block your app.

Toolbar -> Debug -> Windows -> Threads

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

There should be multiple threads and if you double click one you see the line where it is stopping your app.

And if you this line in your code:

Control.CheckForIllegalCrossThreadCalls = false;

Set it to true again. A possible cause for dead locks are background thread accessing controls.

Instead of writing this from a backgroud threads.

button1.Text = "hello"

write this.

this.Invoke(() => button1.Text = "hello");
Jürgen Steinblock
  • 30,746
  • 24
  • 119
  • 189
  • thanks. with the threads I found the edited part of my main question – masterchris_99 Jun 05 '12 at 11:27
  • You could try using `BeginInvoke` rather than `Invoke` which won't wait for the call to return, but I would use a `System.Windows.Forms.Timer`, you are using this code in a Windows Forms context, right? The Windows Forms Timer Tick event fires in the GUI thread, so you don't have to worry about synchronisation. – Jürgen Steinblock Jun 05 '12 at 12:48
  • Currently I use the System.Windows.Forms.Timer and some locks but there is no improvement. – masterchris_99 Jun 06 '12 at 07:12
3

If it's freezing, you are likely looking at a deadlock. One of the best ways I have found to find a deadlock is to use a crash dump and sosex.

Here's a good article on using this technique (it's asp.net, but the same principles apply): http://blogs.msdn.com/b/tess/archive/2010/04/27/debugging-a-classic-readerwriterlock-deadlock-with-sosex-dll.aspx

let the app run until it freezes, and take a hang dump: http://blogs.msdn.com/b/tess/archive/2006/10/16/net-hang-debugging-walkthrough.aspx

JMarsch
  • 21,484
  • 15
  • 77
  • 125
0

Invoke is dangerous and can easily cause deadlocks in unexpected ways I would recommend replacing

this.Invoke((MethodInvoker)...

with

this.BeginInvoke((MethodInvoker)...

which won't block the caller and will probably resolve the problem.

edit if it doesn't you will need to wait until it deadlocks and then use windbg to look at why you are deadlocked.

Yaur
  • 7,333
  • 1
  • 25
  • 36
0

When running from VS it will inject a debugger thread, which changes some message routing. You might have a problem with your Invoke(...) blocking on something that is waiting on a message in the queue, but under the debugger the win messages are processed in a different order.

IIUC you don't need locks with System.Windows.Forms.Timer because it uses win message pump, so timer events are always processed on the GUI thread (unless something else in your app is running code on the TheadPool or in dedicated background threads).

So, nothing in your sample code involves threading, unless the web browser control fires its events on a background thread (in which case POST those back to the UI thread, with BeginInvoke()). Once you've got all the application control running on the main UI thread remove the locks (as a debugging aid). Please post more info about the background processing and any results to date.

yzorg
  • 4,224
  • 3
  • 39
  • 57