How to Use a Backgroundworker

How to use a BackgroundWorker?

You can update progress bar only from ProgressChanged or RunWorkerCompleted event handlers as these are synchronized with the UI thread.

The basic idea is. Thread.Sleep just simulates some work here. Replace it with your real routing call.

public Form1()
{
InitializeComponent();

backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.WorkerReportsProgress = true;
}

private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
backgroundWorker1.ReportProgress(i);
}
}

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}

How to use background worker to loading a form? c#

Here is a sample implementation class from a simple form project. I am using the synchronization context to marshall the progress updates to the UI thread. In the constructor it's getting the context for the current UI thread so it can be used in the background worker thread to provide status updates.

I've also shown you how to cancel a running background worker as well.

public partial class Form1 : Form
{
BackgroundWorker _worker = new BackgroundWorker();
SynchronizationContext _syncContext;

public Form1()
{
InitializeComponent();
_syncContext = SynchronizationContext.Current;
}

private void btnLoadForm_Click(object sender, EventArgs e)
{
_worker.WorkerReportsProgress = true;
_worker.WorkerSupportsCancellation = true;
_worker.DoWork += new DoWorkEventHandler(HandleDoWork);
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(HandleWorkerCompleted);
_worker.ProgressChanged += new ProgressChangedEventHandler(HandleProgressChanged);
_worker.RunWorkerAsync();
}

private void btnCancel_Click(object sender, EventArgs e)
{
if (_worker.WorkerSupportsCancellation)
{
_worker.CancelAsync();
}
}

private void HandleDoWork(object sender, DoWorkEventArgs e)
{
// DO Any work to instantiate the form
System.Threading.Thread.Sleep(2000);

if (_worker.CancellationPending)
{
e.Cancel = true;
}
else
{
Form2 newForm = new Form2();
newForm.ShowDialog();
}
}

private void HandleProgressChanged(object sender, ProgressChangedEventArgs e)
{
// DO Progress Bar Updates Here
SendOrPostCallback callback = new SendOrPostCallback((o) =>
{
label1.Text = "This is my Async content";
});
_syncContext.Send(callback, null);
}

private void HandleWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// DO Any completed step items here
}

}

How to use WPF Background Worker


  1. Add using
using System.ComponentModel;

  1. Declare Background Worker:
private readonly BackgroundWorker worker = new BackgroundWorker();

  1. Subscribe to events:
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;

  1. Implement two methods:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// run all background tasks here
}

private void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
//update ui once worker complete his work
}

  1. Run worker async whenever your need.
worker.RunWorkerAsync();

  1. Track progress (optional, but often useful)

    a) subscribe to ProgressChanged event and use ReportProgress(Int32) in DoWork

    b) set worker.WorkerReportsProgress = true; (credits to @zagy)

Correct usage of BackgroundWorker in WPF

Simple thumb rule is you cannot access UI element from background thread. You are accessing textbox and password control in DoWork which results in an exception.

Fetch user name and password on UI thread and you are good.

string userName = tbLogin.Text;
string password = tbPassword.Password;
bw.DoWork += (o, args) =>
{
user = _viewmodel.Login(userName, password);
};

How to use BackgroundWorker in C#

So let's try to find some answers:

The method worker_DoWork() will be executed within another thread. By calling within that method this.Invoke() you're going to pass the call back to the gui thread, which makes the usage of the background worker useless. Instead within the worker method you have to call the method that needs some time and doesn't interact with the gui. If this called method produces any result (e.g. has a return value) you should write this information into the variable e.Result.

The method worker_RunWorkerCompleted() will be called within the gui thread again. Allowing you to take the result and let it somehow interact with the gui. Due to the fact, that this method will be executed on the gui thread it should be quite simple (or fast) in its doing otherwise your gui is going to freeze again.

So given these informations lets clean up your code:

private void btnFill_Click(object sender, EventArgs e)
{
if (btnFill.Text == "Fill")
{
// Update the gui for the user
// and start our long running task
// (disable buttons etc, cause the
// user is still able to click them!).
picloading.BringToFront();
bgwLoadFile.RunWorkerAsync();
}
}

private void bgwLoadFile_DoWork(object sender, DoWorkEventArgs e)
{
// Let's call the long running task
// and wait for it's finish.
Fill();
}

private void bgwLoadFile_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// We're back in gui thread.
// So let us show some results to the user.
if (e.Cancelled)
{
// To support cancellation, the long running
// method has to check some kind of cancel
// flag (boolean field) to allow fast exit of it.
labelMessage.Text = "Operation was cancelled.";
}
else if (e.Error != null)
{
labelMessage.Text = e.Error.Message;
}

// Hide the picture to allow the user
// to access the gui again.
// (re-enable buttons again, etc.)
picLoading.SendToBack();
}

Background worker in windows form application

In general the BackgroundWorker shouldn't access any UI-Elements. It's an old advice in Winforms that accessing UI-Elements should just happen from the UI-Thread.

You can use the Background-Worker like this:

private void Main(string[] args)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += Bw_DoWork;
bw.RunWorkerCompleted += Bw_RunWorkerCompleted;

//Parameter you need to work in Background-Thread for example your strings
string[] param = new[] {"Text1", "Text2", "Text3", "Text4"};

//Start work
bw.RunWorkerAsync(param);
}

//Do your Background-Work
private void Bw_DoWork(object sender, DoWorkEventArgs e)
{
string[] param = e.Argument as string[];

//Process your long running task

e.Result = null; //Set your Result of the long running task
}

//Taking your results
private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Apply your Results to your GUI-Elements
myTextBox1.Text = e.Result.ToString();
}

Background-Worker is some old school stuff by the way, so if you like to learn something new take a look here and inform yourself about the TPL. This gives you a better handling of asynchronous.

In fact I think it's not really good to store 4gb data in a XML-File. Do you think about a Database? Or split the XML-File in many XML-Files? So you would be able to read data in chunks.

I hope this helps you.

can a BackgroundWorker object in c# be ran without a Windows Forms?

In C# there you can use Tasks or Threads they are both used to run in background in separated execution context ( separated thread )

This is an simple example for using thread

    using System.Threading;

// creating new thread and pass it the delegate to run it

Thread thread = new Thread(new ThreadStart(WorkThreadFunction));
// this command to start the thread
thread.Start();

public void WorkThreadFunction()
{

// do any background work

}


Related Topics



Leave a reply



Submit