Running a BackgroundWorker continuously - c#

I need to be able to continuously run my BackgroundWorker. The DoWork event contains a pool threaded process and the OnComplete updates my UI.
I have not been able to find a way to infinitely loop the BackgroundWorker.RunWorkerAsync() method without the whole program freezing. Any help would be greatly appreciated.

You have to make a loop in your DoWork-Method. To update your UI you shoud use the ProgressChanged-Method. Here is a small example how this can look like
public Test()
{
this.InitializeComponent();
BackgroundWorker backgroundWorker = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
backgroundWorker.DoWork += BackgroundWorkerOnDoWork;
backgroundWorker.ProgressChanged += BackgroundWorkerOnProgressChanged;
}
private void BackgroundWorkerOnProgressChanged(object sender, ProgressChangedEventArgs e)
{
object userObject = e.UserState;
int percentage = e.ProgressPercentage;
}
private void BackgroundWorkerOnDoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker) sender;
while (!worker.CancellationPending)
{
//Do your stuff here
worker.ReportProgress(0, "AN OBJECT TO PASS TO THE UI-THREAD");
}
}

I have done this in the past when needing something to run in the background.
If you try to run the backgroundworker while it is running, you will get an excpetion!
That is why i make the BackGroundWorker start itself when it is done in the completed event.
And then it will loop forever.
private void Main_Load(object sender, EventArgs e)
{
// Start Background Worker on load
bgWorker.RunWorkerAsync();
}
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(1000); // If you need to make a pause between runs
// Do work here
}
private void bgCheck_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Update UI
// Run again
bgWorker.RunWorkerAsync(); // This will make the BgWorker run again, and never runs before it is completed.
}

timer.interval=60000 // 1 min
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
try
{
//Do something
}
catch
{
}
}

on backgroundworker completed event, just start background worker again

If your program is freezing, it may be because your infinitely looping background worker thread is spinning, using 100% CPU. You haven't said why you need it to run in an infinite loop, but you could start by putting a Thread.Sleep in that loop.

Related

How to pause and resume a backgroundworker thats plotting a chart dynamcally? [duplicate]

Let's say I have a background worker like this:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while(true)
{
//Kill zombies
}
}
How can I make this background worker start and stop using a button on a WinForm?
Maybe you can use a manualresetevent like this, I didn't debug this but worth a shot. If it works you won't be having the thread spin its wheels while it's waiting
ManualResetEvent run = new ManualResetEvent(true);
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while(run.WaitOne())
{
//Kill zombies
}
}
private void War()
{
run.Set();
}
private void Peace()
{
run.Reset();
}
Use the CancelAsync method.
backgroundworker1.CancelAsync();
In your loop inside the worker thread.
if (backgroundWorker.CancellationPending) return;
This doesn't happen immediately.
This is how to do it (link to answer below)
By stop do you really mean stop or do you mean pause?
If you mean stop, then this is a piece of cake. Create a button click event handler for the button you want to be responsible for starting the background worker and a button click event handler for the one responsible for stopping it. On your start button, make a call to the background worker method that fires the do_work event. Something like this:
private void startButton_Click(System.Object sender,
System.EventArgs e)
{
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync();
}
On your stop button, make a call to the method that sets the background worker's CancellationPending to true, like this:
private void cancelAsyncButton_Click(System.Object sender,
System.EventArgs e)
{
// Cancel the asynchronous operation.
this.backgroundWorker1.CancelAsync();
}
Now don't forget to check for the CancelationPending flag inside your background worker's doWork. Something like this:
private void KillZombies(BackgroundWorker worker, DoWorkEventArgs e)
{
while (true)
{
if (worker.CancellationPending)
{
e.Cancel = true;
}
}
}
And your doWork method:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
KillZombies(worker, e);
}
I hope this can steer you in the right direction. Some further readings:
http://msdn.microsoft.com/en-us/library/b2zk6580(v=VS.90).aspx
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
http://msdn.microsoft.com/en-us/library/waw3xexc.aspx
I haven't tested this, I have code somewhere that I'll have to see exactly what I did, but something like this is an adaptation of Fredrik's answer:
private bool _performKilling;
private object _lockObject = new object();
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while(true)
{
if (_performKilling)
{
//Kill zombies
}
else
{ //We pause until we are woken up so as not to consume cycles
Monitor.Wait(_lockObject);
}
}
}
private void StartKilling()
{
_performKilling = true;
Monitor.Pulse(_lockObject);
}
private void StopAllThatKilling()
{
_performKilling = false;
]
More complete example of this pattern here:
https://github.com/AaronLS/CellularAutomataAsNeuralNetwork/blob/fe9e6b950e5e28d2c99350cb8ff3157720555e14/CellLifeGame1/Modeling.cs

When does the BackGroundWork RunWorkerCompleted event execute?

I am confused about the BackGroundWorker RunWorkerCompleted event execution timing.
This is my test code
private string hellow="hello";
private void button1_Click(object sender, EventArgs e)
{
bool createAndRunWorkResult = CreateAndRunWork();
if (createAndRunWorkResult)
{
//Do something that need wait RunBackGroundWorkerCompleted execute here.
//MessageBox.Show(hello);
}
}
private bool CreateAndRunWork()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
return true;
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
//Nothing here;
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
hello="aloha";
}
My design workflow is to click the button1 and then do something after RunWorkerCompleted has executed.
But RunWorkerCompleted seems to be located on the bottom of the method stack. In other words: I'm getting createAndRunWorkResult before RunWorkerCompleted executes. What confuses me is if I uncomment MessageBox.Show(hello) in button1_Click, the MessageBox.Show(hello) will wait until worker_RunWorkerCompleted has executed. But, I still get a "hello" messagebox rather than "aloha".
I guess all UI operation will be located below the RunWorkerCompleted at the method stack.
However, I'm not sure if my assumption is correct and if there is a way to force do something only after RunWorkerCompleted has been executed?
The Problem is, that a backgroudnworker is another thread that you can't wait for.
The backgroundworker is telling you when it's finished its work.
so your code should look like this
private string hellow="hello";
private void button1_Click(object sender, EventArgs e)
{
bool createAndRunWorkResult = CreateAndRunWork();
}
private bool CreateAndRunWork()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
return true;
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
//Nothing here;
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
hellow="aloha";
//Do something that need wait RunBackGroundWorkerCompleted execute here.
//MessageBox.Show(hellow);
}
I recommend reading this: http://msdn.microsoft.com/en-us/library/ms173178%28v=vs.120%29.aspx
about threading
BackgroundWorker object is designed to simply run a function on a different thread and then call an event on your UI thread when it's complete, So in your code you should call function which you want to run after RunWorkerCompleted.
There are 3 Steps:
Create a BackgroundWorker object.
Tell the BackgroundWorker object what task to run on the background thread (the DoWork function).
Tell it what function to run on the UI thread when the work is complete (the RunWorkerCompleted function).
If you write function call in your code
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Test();//This is the code which in your case you want to run
}
void Test()
{
hello = "Hola";
MessageBox.Show(hello);
}
you will get HOLA message this is due to step 3 mentioned above. Hope this helps

C# Threading, 1st Task DoSomething, 2nd Task update a WinFormLabel (Realtime)?

Lets say I have Task 1:
private void Task1()
{
//Here is some Code, could be any "longer" Task -
//For Example: Grab all words from a .txt File and fill in a List<String>
}
Then I have an other Task 2:
private void Task2(string word)
{
//So lets say theres a Label on my WinForm..
//Now While Task1 is grabbing the words, Task2 should fill a Label
//with the added 'word' (parameter) - (Task2 will be called from Task1
}
Actually I don't know how to make this possible, or whats the best way. On the UI I should be able to see the Label.Text changing (every word).. So I need to make a second Thread? How could I do this? Maybe someone could help me, cheers
UPDATE:
I tried it now with the Backgroundworker, but something seems to be false.. its actually not working, nothing happens on the form
Code:
public void CreateAndSaveAMatch(DateTime date) //That method is being called several times
{
//HERE IS CODE, WHICH CREATES AND SAVES A MATCH
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync(date);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
backgroundWorker1.ReportProgress(0, Convert.ToDateTime(e.Argument).ToShortDateString());
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = (string)e.UserState; //here on the Label I would like to show the Date
}
Ok, try this. This is a simple example that will show you how to solve your problem using BackgroundWorker. Also note that there are many other solutions. To use this example create a Form in a new project that only has a button and a label. Also note that this is a supplement of the other answers which were correct.
public partial class Form1 : Form
{
BackgroundWorker createAndSaveAMatchBGW;
public Form1()
{
InitializeComponent();
createAndSaveAMatchBGW = new BackgroundWorker();
createAndSaveAMatchBGW.DoWork += new DoWorkEventHandler(createAndSaveAMatchBGW_DoWork);
createAndSaveAMatchBGW.ProgressChanged += new ProgressChangedEventHandler(createAndSaveAMatchBGW_ProgressChanged);
createAndSaveAMatchBGW.RunWorkerCompleted += new RunWorkerCompletedEventHandler(createAndSaveAMatchBGW_RunWorkerCompleted);
createAndSaveAMatchBGW.WorkerReportsProgress = true;
}
private void button1_Click(object sender, EventArgs e)
{
createAndSaveAMatchBGW.RunWorkerAsync(DateTime.Now);
}
void createAndSaveAMatchBGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("BackgroundWorker finished");
}
void createAndSaveAMatchBGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = ((DateTime)e.UserState).ToString("ss");
}
void createAndSaveAMatchBGW_DoWork(object sender, DoWorkEventArgs e)
{
//BackgroundWorker does something for a 10 seconds, each second it Reports
BackgroundWorker bgw = (BackgroundWorker)sender;
DateTime dt = (DateTime) e.Argument;
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
dt = dt.AddSeconds(1);
bgw.ReportProgress(0, dt);
}
}
}
And if you report from CreateAndSave... method only once per its execution, then you can use this code:
BackgroundWorker createAndSaveAMatchBGW;
public Form1()
{
InitializeComponent();
createAndSaveAMatchBGW = new BackgroundWorker();
createAndSaveAMatchBGW.DoWork += new DoWorkEventHandler(createAndSaveAMatchBGW_DoWork);
createAndSaveAMatchBGW.RunWorkerCompleted += new RunWorkerCompletedEventHandler(createAndSaveAMatchBGW_RunWorkerCompleted);
}
private void button1_Click(object sender, EventArgs e)
{
createAndSaveAMatchBGW.RunWorkerAsync(DateTime.Now);
}
void createAndSaveAMatchBGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
label1.Text = ((DateTime)e.Result).ToString();
}
void createAndSaveAMatchBGW_DoWork(object sender, DoWorkEventArgs e)
{
DateTime dt = (DateTime) e.Argument;
//you do something with your DateTime
dt = dt.AddDays(10);
e.Result = dt;
}
Use BackgroundWorker for reporting progress from first task. Drag this component from toolbox to your form, and subscribe to DoWork and ProgressChanged events. Also set property WorkerReportsProgress to true. Then start you first task asynchronously:
// this will execute code in `DoWork` event handler
backgroundWorker1.RunWorkerAsync();
Next - use userState object to pass processed words:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// grab words in a loop and report progress
backgroundWorker1.ReportProgress(0, word);
}
And last step - update label in ProgressChanged event handler
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text += (string)e.UserState; // this is your grabbed word
}
The simplest way to achieve this kind of thing is using BackgroundWorker.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
BackgroundWorker automatically handles thread marshalling and provides events that allow you to update the UI. The event handlers run on the UI thread.
The things you do in Task1 could be moved into a BackgroundWorker, and the updates to the UI that you propose to do in Task2 can actually be in response to progress events from BackgroundWorker.
ProgressChangedEventArgs provides for user-defined data that could hold the current word.
However, Winforms (and indeed pretty much any UI) will not be able to keep up with a separate CPU thread just loading words from a file if you intend to show every word you load.
Task1 could be started on a separate thread.
You wouldn't actually need a Task2 unless there was some complex logic being performed to update the TextBox. You you really need to do is use TextBox.Invoke() to invoke the update on the UI Thread from Task1.

C# UI Thread Unresponsive

I have a function that adds a lot of files to a collection and does a lot of actions on each of them.
This causes the program (main thread) to become unresponsive.
How can I determine the cause and address the problem?
Use the BackgroundWorker object. You can inform the user with the progress of the operation by using the ReportProgress and ProgressChanged event.
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// .. stuff that takes long
backgroundWorker1.ReportProgress(10);
// .. stuff that takes long
backgroundWorker1.ReportProgress(20);
// .. stuff that takes long
backgroundWorker1.ReportProgress(100);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Done !
}
Use another thread.
Thread t = new Thread(new ThreadStart( () => {
IntensiveCalculationCode();
}));
t.Start();
You can also invoke the UI thread from inside the thread by invoking the dispatcher. They are not exactly the same on Windows Forms and WPF though.

C# : How to pause the thread and continue when some event occur?

How can I pause a thread and continue when some event occur?
I want the thread to continue when a button is clicked.
Someone told me that thread.suspend is not the proper way to pause a thread.
Is there another solution?
You could use a System.Threading.EventWaitHandle.
An EventWaitHandle blocks until it is signaled. In your case it will be signaled by the button click event.
private void MyThread()
{
// do some stuff
myWaitHandle.WaitOne(); // this will block until your button is clicked
// continue thread
}
You can signal your wait handle like this:
private void Button_Click(object sender, EventArgs e)
{
myWaitHandle.Set(); // this signals the wait handle and your other thread will continue
}
Indeed, suspending a thread is bad practice since you very rarely know exactly what a thread is doing at the time. It is more predictable to have the thread run past a ManualResetEvent, calling WaitOne() each time. This will act as a gate - the controlling thread can call Reset() to shut the gate (pausing the thread, but safely), and Set() to open the gate (resuming the thread).
For example, you could call WaitOne at the start of each loop iteration (or once every n iterations if the loop is too tight).
You can try this also
private static AutoResetEvent _wait = new AutoResetEvent(false);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Dosomething();
}
private void Dosomething()
{
//Your Loop
for(int i =0;i<10;i++)
{
//Dosomething
_wait._wait.WaitOne();//Pause the loop until the button was clicked.
}
}
private void btn1_Click(object sender, EventArgs e)
{
_wait.Set();
}

Categories