11

I am developing a WPF client application.This app sends data periodically to the webservice. When user logged into the app I want run particular method every 5 mts to send data to the .asmx service.

My question is whether I need to use threading or timer.This method execution should happen while user is interacting with the application. i.e without blocking the UI during this method execution

Any resources to look for ?

Yusubov
  • 5,815
  • 9
  • 32
  • 69
umsateesh
  • 163
  • 1
  • 1
  • 12

3 Answers3

36

I would recommend the System.Threading.Tasks namespace using the new async/await keywords.

// The `onTick` method will be called periodically unless cancelled.
private static async Task RunPeriodicAsync(Action onTick,
                                           TimeSpan dueTime, 
                                           TimeSpan interval, 
                                           CancellationToken token)
{
  // Initial wait time before we begin the periodic loop.
  if(dueTime > TimeSpan.Zero)
    await Task.Delay(dueTime, token);

  // Repeat this loop until cancelled.
  while(!token.IsCancellationRequested)
  {
    // Call our onTick function.
    onTick?.Invoke();

    // Wait to repeat again.
    if(interval > TimeSpan.Zero)
      await Task.Delay(interval, token);       
  }
}

Then you would just call this method somewhere:

private void Initialize()
{
  var dueTime = TimeSpan.FromSeconds(5);
  var interval = TimeSpan.FromSeconds(5);

  // TODO: Add a CancellationTokenSource and supply the token here instead of None.
  RunPeriodicAsync(OnTick, dueTime, interval, CancellationToken.None);
}

private void OnTick()
{
  // TODO: Your code here
}
Erik
  • 12,730
  • 5
  • 36
  • 42
  • 2
    Thanks! I really like your approach! – lightxx Mar 18 '13 at 07:30
  • I like the approach but if I create a WriteableBitmap before the while{} and WritePixels into the while{} I receive Threading.Dispatcher.VerifyAccess() I thought Method/Task was in a single Thread ? – Jean-Philippe Encausse Aug 08 '13 at 20:10
  • Is this approach is Parallel ? – Jean-Philippe Encausse Aug 12 '13 at 22:34
  • 1
    This works really well!! Great code. Im using it to check a local file (first line is true or false) content value change and update the UI elements visibility. – BENN1TH Jul 21 '15 at 08:15
  • thank you I also using your method to call an async task periodically – Imam Baihaqi Jun 13 '16 at 08:09
  • @Jean-PhilippeEncausse Tasks do not really translate to threads in the traditional sense. When you `await` a task, the current context (thread) is captured. The task you are awaiting will typically be executed on a thread pool thread and the continuation (code after the `await`) will be queued to run on the captured context (before the `await`). If you use `Task.ConfigureAwait(false)`, it tells the compiler to not worry about capturing the context and the continuation is run on the thread pool instead. – Erik Jul 03 '16 at 02:57
  • Nice, but: (1) Instead of `onTick?.Invoke();` it makes much more sense to check for nullity at the start and throw `ArgumentNullException`. You should do that in an outer non-async method though, so that the exception is fired on the original thread (before a task is created by the compiler async transformation).(2) Instead of checking `IsCancellationRequested` you should be using `ThrowIfCancelationRequested`. (3) This will not necessarily run every `interval` because you depend on the time `onTick` took. This could be the desired behavior, but it wasn't clearly specified by the OP. – Ohad Schneider Nov 04 '16 at 17:24
  • This really works for me too! I implemented a timer that shows a countdown for each row of a GridView in WPF, and called in the "OnTick" a function to update the remaining seconds in the binded data model directly, as explained here: https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/how-to-implement-property-change-notification?redirectedfrom=MSDN&view=netframeworkdesktop-4.8 . – marcor92 May 21 '23 at 22:25
12

You need to use Timer class. There are multiple built-in timers and it depends on the requirement which timer to use.

  1. System.Timers.Timer: This is more suitable for mutlithreaded access. Instances of this timer are threadsafe.

  2. System.Threading.Timer : Instances of this timer are not thread safe.

  3. System.Windows.Threading.DispatcherTimer -> It sends event to Dispatcher thread (and is not multithreaded). This is useful if you need to update UI.

  4. System.Windows.Forms.Timer -> This timer raises events in UI thread. This is optimized for windows forms, and not to be used in WPF.

Following is an interesting read.
Comparing the Timer Classes in the .NET Framework Class Library

Tilak
  • 30,108
  • 19
  • 83
  • 131
  • Thanks for your link but I have some difficulty understanding Requirement : Client can interact smoothly with the WPF application, simultaneously sending data to the service.Both things should happen at same time. This is my req which built in timer I need to use ? – umsateesh Jan 12 '13 at 19:17
  • Are they separate (client interaction, and sending data) or tied together as dependent parts – Tilak Jan 12 '13 at 19:19
  • Yes they are independent.User can insert,Update,delete data but We send the data from Database to service. – umsateesh Jan 12 '13 at 19:47
  • Then use [`System.Timers.Timer`](http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx), Call your methods in `Timer.Elapsed` event – Tilak Jan 12 '13 at 19:51
2

If you want the method to execute on a different thread than the UI one, use System.Threading.Timer. Otherwise (but I don't think it's your case), use System.Windows.Threading.DispatcherTimer.

e_ne
  • 8,340
  • 32
  • 43
  • OK I will write this in Mainwindow.xaml.cs main method. Does this timer tick even when I open a child window? OR what is the best place to put this code so that it ticks where ever i am in the application main window or any one of the child windows? – umsateesh Jan 12 '13 at 19:22
  • @sateeshmunagala The context you place it on is not relevant, as long as you can be sure that its container class isn't disposed while you are using the timer. – e_ne Jan 12 '13 at 19:49