Execute task in background in WPF application
Asked Answered
B

3

23

Example

private void Start(object sender, RoutedEventArgs e)
{
    int progress = 0;
    for (;;)
    {
        System.Threading.Thread.Sleep(1);
        progress++;
        Logger.Info(progress);
    }
}

What is the recommended approach (TAP or TPL or BackgroundWorker or Dispatcher or others) if I want Start() to

  1. not block the UI thread
  2. provide progress reporting
  3. be cancelable
  4. support multithreading
Bradleybradly answered 24/1, 2014 at 7:12 Comment(2)
J
34

With .NET 4.5 (or .NET 4.0 + Microsoft.Bcl.Async), the best way is to use Task-based API and async/await. It allows to use the convenient (pseudo-)sequential code workflow and have structured exception handling.

Example:

private async void Start(object sender, RoutedEventArgs e)
{
    try
    {
        await Task.Run(() =>
        {
            int progress = 0;
            for (; ; )
            {
                System.Threading.Thread.Sleep(1);
                progress++;
                Logger.Info(progress);
            }
        });
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

More reading:

How to execute task in the WPF background while able to provide report and allow cancellation?

Async in 4.5: Enabling Progress and Cancellation in Async APIs.

Async and Await.

Async/Await FAQ.

Johnsonian answered 24/1, 2014 at 7:38 Comment(10)
Can I use multithread and multicore if I use Task based API? By the way, BackgroundWorker able to do calcellation and progress reporting. What are the difference between BackgroundWorker and Task based api?Bradleybradly
@publicENEMY, Task-based API makes BackgroundWorker obsolete, read this: Task.Run vs BackgroundWorker. Task.Run uses a ThreadPool thread to run your task, so yes, it certainly supports multithreading and multicore. There's some learning curve, but very well worth it.Johnsonian
@publicENEMY do not worry about multiple cores. The Operating system assigns threads to cores (known as processor affinity) and tries to use all the cores if it can! Any method for asynchronous programming uses Threads if you drill down deep enough.Kenwood
Since I can only mark 1 answers, Im gonna mark Task Based Api just because its newer. AFAIK, BackgroundWorker can also be considered answer. Thanks.Bradleybradly
@publicENEMY, BackgroundWorker can still be used successfully, and low-level thread API like ThreadPool.QueueUserWorkItem or new Thread() can get the job done, too. Although, it wouldn't be so pleasant to code it as with Task/async/await, IMO.Johnsonian
+1 for the added resources one more url that I found helpful. msdn.microsoft.com/en-us/library/vstudio/hh191443.aspxViniferous
@Noseratio The answer is not complete, point 3 (Cancellation) is missing here in your code example! It would be nice if you would add it, without users having to leave SO proposed by your link.Dracula
@Legends, I have a complete example in another answer here.Johnsonian
Thread.Sleep is a bad practice in async! System.Threading.Thread.Sleep(1); must be replaced with await Task.Delay(1);Earthenware
Thread.Sleep is used in this specific case to simulate a quantum of synchronous CPU-bound work, which is being offloaded to a pool thread (rather than for creating delays). That's what the question was about.Johnsonian
P
7

The best way to do this is by using a BackgroundWorker.

The reason I point this one out is it is specially designed to process work in the background while leaving the UI thread available and responsive. It also has built in Progress notifications and supports Cancellation.

I suggest looking at a few examples of a the BackgroundWorker.

Now when you start looking into the background worker there is one point Cancellation that you will have to dig deeper into. Setting the cancel property of a background worker doesnt cancel the background worker, this just raises a flag for your running method to interogate at regular intervals and gracefully stop processing.

Here is one of my posts from awhile ago talking about cancelling a background worker https://mcmap.net/q/430080/-backgroundworker-questions-on-cancellation

Finally. Asyncronous does not mean multi-core or even multi-thread. (WIKI)

Prado answered 24/1, 2014 at 7:18 Comment(1)
You were right about BackgroundWorker support cancellation and progress reporting. Thanks.Bradleybradly
T
1

You can execute an operation on a separate thread in WPF using the BackgroundWorker Class.

check this example How to use WPF Background Worker

And read about the class on MSDN here http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Tana answered 24/1, 2014 at 7:17 Comment(4)
I totally forgot about BackgroundWorker. I was under the impression that BackgroundWorker are for Winform and WPF equivalent is Dispatcher class. By the way, AFAIK BackgroundWorker doesnt support multithread. Correct me if im wrong.Bradleybradly
"The most reliable way to create a multithreaded application is to use the BackgroundWorker component. This class manages a separate thread dedicated to processing the method that you specify. " From msdn.microsoft.com/en-us/library/ck8bc5c6.aspxTana
@publicENEMY background worker is a helper class for running async operations and reporting progress You can use it in winforms and wpf because the SynchronizationContext mechanism is consistent for both. Every winforms object wraps an instance of WindowsFormsSynchronizationContext (allowing access to the UI thread) but WPF exposes the actual message pump as a Dispatcher/ This contains a DispatcherSynchronizationContext.Kenwood
@SQL.NETWarrior Thanks for the link. Makes it easy to decide.Bradleybradly

© 2022 - 2024 — McMap. All rights reserved.