1

I've run into this several times. My app receives some event (e.g. WndProc) and needs to return quickly. The code that needs to run takes some time, and does not need to be executed before returning from the event handler.

My current solution is to start a timer for a short time, and in the Tick event - run that code.

But that seems like the wrong tool for this case, and is prone to some errors (like running the code more than once, for example).

So, is there any ExecuteWhenThisThreadIsIdle scheme?

EDIT

A C#/.NET solution would be best, but a framework specific solution would be welcome too. Mainly Winforms. (But also WPF, UWP, Xamarin.Forms, ...)

The code needs to run on the same thread as the event handler. (Usually the UI thread.)

ispiro
  • 26,556
  • 38
  • 136
  • 291
  • 2
    Why not just use `Task.Run` to create a Task that will be run by the default TaskScheduler (on another thread) as soon as the system has available resources? – Camilo Terevinto Feb 07 '18 at 11:33
  • @CamiloTerevinto Because the code needs to run on the same thread as the event handler. (I think I'll edit this into the question.) Thanks. I edited it now. – ispiro Feb 07 '18 at 11:34
  • 2
    In that case, you'll need to add the relevant UI framework tag (WPF, WinForms, WebForms?) – Camilo Terevinto Feb 07 '18 at 11:36
  • @mjwills At least Forms.Timer keeps `Tick`ing until stopped. But this was just an example. – ispiro Feb 07 '18 at 11:36
  • @CamiloTerevinto I was wondering if there was a **C#/.NET** solution, as this comes up in all of those you mentioned (plus UWP...). But a framework-specific solution would be welcome too. – ispiro Feb 07 '18 at 11:38
  • 2
    The solution will most likely depend on the framework used. This question should be narrowed down. – Patrick Hofman Feb 07 '18 at 11:40
  • 1
    The problem is that, AFAIK, the synchronization contexts between the different frameworks work in completely different ways (this is my understanding from looking at the classes, though, would love to have this backed up by a more knowledgeable person), so I am not sure if there's something that will work cross-platform there – Camilo Terevinto Feb 07 '18 at 11:40
  • @mjwills I just edited that into the question. Best a general C# one, but any one would be welcome. – ispiro Feb 07 '18 at 11:41
  • How about subscribing to the [`Application.Idle`](https://msdn.microsoft.com/en-us/library/system.windows.forms.application.idle%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) event? – Matthew Watson Feb 07 '18 at 11:41
  • @MatthewWatson That's exactly the type of solution I assumed existed. Thanks! (You can transform your comment into an answer.) – ispiro Feb 07 '18 at 11:44
  • @mjwills Yes. Thanks! (You can convert your comment into an answer.) – ispiro Feb 07 '18 at 12:01

2 Answers2

2

In WinForms, you can subscribe to Application.Idle.

For example ...

private bool _wndProcEventHooked = false;

protected override void WndProc(ref Message m) {
    // Run your code here
}

private void Application_Idle(Object sender, EventArgs e) { 
    if (!this._wndProcEventHooked) {
        // Hook your wndProc event here.
        this._wndProcEventHooked = true;
    }
}
Patrick
  • 5,526
  • 14
  • 64
  • 101
1

In WPF this can be done using DispatcherTimer:

var timer = new DispatcherTimer
    (
    TimeSpan.FromMinutes(10),
    DispatcherPriority.ApplicationIdle,// Or DispatcherPriority.SystemIdle
    (s, e) => MessageBox.Show("Timer"),
    Application.Current.Dispatcher
    );
mjwills
  • 23,389
  • 6
  • 40
  • 63