1

I'm using a Threading.Timer to execute a task on the hour every hour, but when the timer ticks, the app always crashes when processing the code to execute in the tick. It crashes with no exceptions or warnings, even if I put the whole thin in a try/catch. Very strange. Below is my setup and any help would be appreciated! It seems like crashes when it tries to access the TextBox GrepCmdTextBox, but I thought reading from another thread was okay, just not writing.

Setting up timer:

var timeOfDay = DateTime.Now.TimeOfDay;
var nextHour = TimeSpan.FromHours(Math.Ceiling(timeOfDay.TotalHours));
var delta = (nextHour - timeOfDay).TotalMilliseconds;
System.Threading.Timer NextHourTimer = new System.Threading.Timer(new System.Threading.TimerCallback(NextHourTimer_Tick), null, (long)delta, (long)TimeSpan.FromHours(1).TotalMilliseconds);

Tick event:

private void NextHourTimer_Tick(object sender)
    {
        // If thread is not null and is busy, cancel and restart
        if (MonitoringThread != null)
        {
            if (MonitoringThread.TailThread.IsBusy)
            {
                MonitoringThread.TailThread.CancelAsync();
                System.Threading.Thread.Sleep(50);

                // Get grep command, if specified
                string optionalGrep = String.Empty;
                if (GrepCmdTextBox.Text.StartsWith("grep") || GrepCmdTextBox.Text.StartsWith("egrep"))
                    optionalGrep = " | " + GrepCmdTextBox.Text;

                MonitoringThread.TailThread.RunWorkerAsync(optionalGrep);
            }
        }
    }
Hershizer33
  • 1,206
  • 2
  • 23
  • 46
  • The runtime must throw _some_ exception. Enable the throwing of all exceptions and tell us what it is doing... – MoonKnight Oct 30 '12 at 14:45
  • @Killercam I don't know man, I don't see anything... where would this option to enable all exceptions be? – Hershizer33 Oct 30 '12 at 14:46
  • If you are using VS2010, then, for a start you can enable automatic throwing on any exceptions from the menu 'Debug' > 'Exceptions...'. Then check all CLR exceptions and re-run the code. Add additional exceptions that you may think are relevent. If this does not work, this maybe an unmanaged code exception. This time, go to you Project Properties, then on the 'Debug' tab; check 'Enable unmanaged code debugging' - then tell us what you see: at this point I may (or may not!) be able to help you further... – MoonKnight Oct 30 '12 at 14:55
  • @Killercam Thanks for the tip! The new exception I now see was that the BackgroundWorker wasn't fully canceled yet from the `CancelAsync()`, so I guess waiting 50ms wasn't long enough... Is there better way to loop until its fully cancelled before I call `RunWorkerAsync()`? – Hershizer33 Oct 30 '12 at 15:08
  • I suppose Disposing the object and recreating it would not be unreasonable in this case seeing as it is once an hour. – MoonKnight Oct 30 '12 at 15:16
  • @Killercam Yeah [this basically suggested the same](http://stackoverflow.com/a/7045067/643619). He argues that creating them is very cheap, so just new it. If you want to propose that as the answer Ill accept it for ya! – Hershizer33 Oct 30 '12 at 15:20

1 Answers1

2

Cancelling the asynchronous process can take time, the background thread will have to 'finalize', returning from DoWork() and waiting for an opportunity to run the RunWorkerCompleted event, if any.

Instead of cancellation, in this case it would be better to cancel then Dispose() the object, creating a new BGW, as they are as 'cheap-as-chips'.

I hope this helps.

MoonKnight
  • 23,214
  • 40
  • 145
  • 277