I have a WinForms application in which my background worker is doing a sync task, adding new files, removing old ones etc.
In my background worker code I want to show a custom form to user telling him what will be deleted and what will be added if he continues, with YES/NO buttons to get his feedback.
I was wondering if it is ok to do something like this in background worker's doWork method? If not, how should I do it?
Please advise..
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
MyForm f = new MyForm();
f.FilesToAddDelete(..);
DialogResult result = f.ShowDialog();
if(No...)
return;
else
//keep working...
}
BackgroundWorker has already implemented functionality of reporting progress, completion and cancellation - so you don't need to implement it by yourself. Usage of Thread gives you more control over the async process execution (e.g. thread priority or choosing beetween foreground/background thread type).
In the Toolbox pane, please double-click on the BackgroundWorker icon. This will add a BackgroundWorker1 instance to the tray at the bottom of the screen. Tip You can change some properties of the BackgroundWorker by right clicking on it and selecting Properties.
BackgroundWorker makes the implementation of threads in Windows Forms. Intensive tasks need to be done on another thread so the UI does not freeze. It is necessary to post messages and update the user interface when the task is done.
BackgroundWorker, is a component in . NET Framework, that allows executing code as a separate thread and then report progress and completion back to the UI.
If you try this you will see for yourself that it will not work because the BackgroundWorker
thread is not STA (it comes from the managed thread pool).
The essence of the matter is that you cannot show user interface from a worker thread¹, so you must work around it. You should pass a reference to a UI element of your application (the main form would be a good choice) and then use Invoke
to marshal a request for user interaction to your UI thread. A barebones example:
class MainForm
{
// all other members here
public bool AskForConfirmation()
{
var confirmationForm = new ConfirmationForm();
return confirmationForm.ShowDialog() == DialogResult.Yes;
}
}
And the background worker would do this:
// I assume that mainForm has been passed somehow to BackgroundWorker
var result = (bool)mainForm.Invoke(mainForm.AskForConfirmation);
if (result) { ... }
¹ Technically, you cannot show user interface from a thread that is not STA. If you create a worker thread yourself you can choose to make it STA anyway, but if it comes from the thread pool there is no such possibility.
I usually create a method to execute a delegate on the UI thread:
private void DoOnUIThread(MethodInvoker d) {
if (this.InvokeRequired) { this.Invoke(d); } else { d(); }
}
With this, you can change your code to:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
DialogResult result = DialogResult.No;
DoOnUIThread(delegate() {
MyForm f = new MyForm();
f.FilesToAddDelete(..);
result = f.ShowDialog();
});
if(No...)
return;
else
//keep working...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With