Difference between BackgroundWorker and Task.Run

4

Generally when I had to do some operation in background , mainly involving progress bar update or labels I used BackgroundWorker , with its events WorkerReportsProgress and DoWork .

Recently I came across the source of another developer who used Task.Run() with await and interface IProgress .

Is there a significant performance difference or is one method more recommended than the other?

    
asked by anonymous 31.10.2016 / 17:48

2 answers

5

Let's look at the BackgroundWorker interface. (I just put the most relevant information).

Methods

  • CancelAsync() - cancels an operation
  • RunWorkerAsync() - woker starts working
  • ReportProgress() - Invokes 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 has completed part of his work
  • RunWorkerCompleted - This event is called when woker has completed its work

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

Now I have to prove that 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)

There are two things to resolve: cancellation and progress report.

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 does not have is progress report and hence the need for something extra, such as IProgress . That's simple to implement.

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

    
31.10.2016 / 18:17
6

Significant I could not say. The mechanisms are very different, but they serve for more or less the same thing, at least if 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.

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

There is nothing wrong with continuing with the old form if you prefer, but is considered obsolete .

Of course, if comparing Task.Run() with no 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 an operation that does not hang the UI:

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

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

    
31.10.2016 / 18:06