Async/await vs BackgroundWorker
async/await is designed to replace constructs such as the BackgroundWorker
. While you certainly can use it if you want to, you should be able to use async/await, along with a few other TPL tools, to handle everything that's out there.
Since both work, it comes down to personal preference as to which you use when. What is quicker for you? What is easier for you to understand?
C# backgroundworker RunworkerCompleted vs async await
Depend on what kind of work your MCIATS1Worker_DoWork
method do, you can consider to use async-await
approach, which makes code a little bid more cleaner.
private async Task MCIATS1WorkerDoWorkAsync()
{
await Task.Delay(1000) // do something asynchronously for 1 second
}
private async void MainWindow_Load(object sender, EventArgs e)
{
for (int i = 1; i <= 10; i++)
{
//some code
await MCIATS1WorkerDoWorkAsync();
MessageBox.Show("hello world");
}
}
Message box will be shown 10 times every 1 second. await
keyword will continue loop only after MCIATS1WorkerDoWorkAsync
method has successfully finished.
With async-await
your form will remain responsive and if DoWork
method do some IO operations, then you will not start another thread (as BackgroundWorker do) and whole execution will happens on one thread.
Updating background worker to async-await
I have a blog series that covers this in detail.
In short, BackgroundWorker
is replaced by Task.Run
, and ReportProgress
(and friends) is replaced by IProgress<T>
.
So, a straightforward translation would look like this:
async void SaveButtonClick(object sender, EventArgs e)
{
if (SaveFileDialog.ShowDialog() == DialogResult.OK)
{
ProgressWindow = new ProgressForm();
ProgressWindow.SetPercentageDone(0);
var progress = new Progress<int>(ProgressWindow.SetPercentageDone);
var task = SaveAndClose(SaveFileDialog.FileName, progress));
ProgressWindow.ShowDialog(this);
await task;
}
}
async Task SaveAndClose(string path, IProgress<int> progress)
{
await Task.Run(() => Save(path, progress));
ProgressWindow.Close();
}
void Save(string path, IProgress<int> progress)
{
// open file
for (int i=0; i < 100; i++)
{
// get some stuff from UI
// save stuff to file
if (progress != null)
progress.Report(i);
}
// close file
}
Notes for improvements:
- It's not usually a good idea to have background threads reaching into the UI (
// get some stuff from UI
). It would probably work better if you could collect all the information from the UI before callingTask.Run
and just pass it into theSave
method.
Using await Task inside backgroundWorker is changing my status to complete
You can't use await
inside a BackgroundWorker
's DoWork
. I recommend replacing BackgroundWoker
completely with Task.Run
:
Task task = null;
var timer = new Timer();
timer.Interval = 10000;
timer.Tick += Timer_Tick;
timer.Start();
private static async void Timer_Tick(object sender, EventArgs e)
{
if (task == null)
{
task = Task.Run(() => DoWorkAsync(frm));
try { await task; }
finally { task = null; }
}
}
private static async Task DoWorkAsync(Main frm)
{
using (var client = new HttpClient())
{
var result = await client.GetAsync(uri);
//message to user for answering, then return it to server again
}
}
Side note: I changed System.Timers.Timer
to System.Windows.Forms.Timer
so that the task
variable is always accessed from the UI thread.
BackgroundWorker or Task, which to implement?
BackgroundWorker
has been superseded by Tasks
and in general you should use the latter when possible.
Note that besides Tasks having more features, there are also subtle differences which may be relevant. For instance, a Task
may not necessarily be run on a different thread, while BackgroundWorker.DoWork
does.
Arguably, BackgroundWorker
is easier to use and you will still need it when developing in .NET versions prior to 4.
I wouldn't recommend refactoring your existing code, just start using Tasks in your new base. I also find Tasks easier to integrate with UIs but that may be subjective.
Related Topics
Identify If a String Is a Number
Why Did I Get the Compile Error "Use of Unassigned Local Variable"
How to Pass Table Value Parameters to Stored Procedure from .Net Code
How to Find Out Which Process Is Locking a File Using .Net
How to Write Unicode Characters to the Console
One Dbcontext Per Web Request... Why
Capture Screenshot of Active Window
How to Find the Method That Called the Current Method
Using .Net, How to Find the Mime Type of a File Based on the File Signature Not the Extension
Is There a Reason For C#'S Reuse of the Variable in a Foreach
How to Get a User'S Client Ip Address in Asp.Net
Implementing Inotifypropertychanged - Does a Better Way Exist
Use of Finalize/Dispose Method in C#