Difference is between Backgroundworker and Task.Run()?

Asked

Viewed 651 times

5

Usually when I had to do some operation on background, mainly involving progress bar update or Labels I used to use the BackgroundWorker, with your events WorkerReportsProgressand DoWork.

I recently came across the source of another developer using Task.Run() with await and the interface IProgress.

There is significant difference in performance or when one method is more recommended than the other?

2 answers

7

Significant I wouldn’t know how to say it. The mechanisms are very different, but they serve for more or less the same thing, at least if the Task.Run() is used to solve the same problem.

Obviously the way to use it is quite different, especially if you want to be notified of progress, but the result does not change much.

The BackgroundWorker would not have been created if . NET had the await from the beginning. It’s more modern, it’s the right way to do it, it’s better thought out and it’s a more general mechanism. Certainly the most modern way is simpler to write and for me it is more intuitive.

There’s nothing wrong with continuing the old way if you really prefer, but is considered obsolete.

Of course if you compare the Task.Run() context does not give, it is more powerful, flexible and general. The comparison only fits in a very specific form of its use.

Example of operation that does not lock the UI:

private async void buttonGeraBoletos_Click(object sender, EventArgs e) {
    await Task.Run(() => GeraBoletos());
    MessageBox.Show("Tudo gerado");
}

I put in the Github for future reference.

You can do it in parallel too, which can end much faster.

6


Let’s look at the interface of Backgroundworker (I put only the most relevant infomacao).

Methods

  • CancelAsync() - cancels an operation
  • RunWorkerAsync() - the Woker starts working
  • ReportProgress() - Invokes the ProgressChanged

Events

  • DoWork - This event is called when the worker starts working
  • ProgressChanged - This event is called when the worker wants to notify the user-interface that completed part of his work
  • RunWorkerCompleted - This event is called when Woker completed its work

An example of its use is in link that I mentioned.


Now I have to prove I can do the same with a Task.

var task = Task.Run(() => {/*O trabalho vai aqui*/});
var result = await task; // A task acaba aqui (Do Work + RunWorkerCompleted)

Two things left to solve: cancellation and report of progress.

Cancellation is done with a Cancellationtoken

var cancela = new CancellationTokenSource();
var task = Task.Run(() => {
    cancela.Token.ThrowIfCancellationRequested();/*pode chamar mais vezes*/
    /*O trabalho vai aqui*/
}, cancela.Token);
cancela.Cancel();
var result = await task; // A task acaba aqui (Do Work + RunWorkerCompleted)

But in fact the only thing that Task there is no progress report and hence the need for something extra, such as IProgress. That is simple to implement.

Summarizing the Task does the same, with less code (or cleaner code) and it actually replaces the old BackgroundWorker.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.