Observe the following piece of code:
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += OnAsyncOperationCompleted;
Try using the AutoResetEvent class like this:
var doneEvent = new AutoResetEvent(false);
var bw = new BackgroundWorker();
bw.DoWork += (sender, e) =>
{
try
{
if (!e.Cancel)
{
// Do work
}
}
finally
{
doneEvent.Set();
}
};
bw.RunWorkerAsync();
doneEvent.WaitOne();
Caution: You should make sure that doneEvent.Set()
is called no matter what happens. Also you might want to provide the doneEvent.WaitOne()
with an argument specifying a timeout period.
Note: This code is pretty much a copy of Fredrik Kalseth answer to a similar question.
In OpenCV exists function WaitKey. Ir allows solve this issue in that way:
while (this->backgroundWorker1->IsBusy) {
waitKey(10);
std::cout << "Wait for background process: " << std::endl;
}
this->backgroundWorker1->RunWorkerAsync();
I used Tasks with a BackgroundWorker
You can create any number of tasks and add them to a list of tasks. The worker will start when a task is added, restart if a task is added while the worker IsBusy, and stop once there are no more tasks.
This will allow you to update the GUI asynchronously as much as you need to without freezing it.
This works as is for me.
// 'tasks' is simply List<Task> that includes events for adding objects
private ObservableCollection<Task> tasks = new ObservableCollection<Task>();
// this will asynchronously iterate through the list of tasks
private BackgroundWorker task_worker = new BackgroundWorker();
public Form1()
{
InitializeComponent();
// set up the event handlers
tasks.CollectionChanged += tasks_CollectionChanged;
task_worker.DoWork += task_worker_DoWork;
task_worker.RunWorkerCompleted += task_worker_RunWorkerCompleted;
task_worker.WorkerSupportsCancellation = true;
}
// ----------- worker events
void task_worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (tasks.Count != 0)
{
task_worker.RunWorkerAsync();
}
}
void task_worker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
foreach (Task t in tasks)
{
t.RunSynchronously();
tasks.Remove(t);
}
}
catch
{
task_worker.CancelAsync();
}
}
// ------------- task event
// runs when a task is added to the list
void tasks_CollectionChanged(object sender,
System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (!task_worker.IsBusy)
{
task_worker.RunWorkerAsync();
}
}
Now all you need is to create a new Task and add it to the List<>. It will be run by the worker in the order it was placed into the List<>
Task t = new Task(() => {
// do something here
});
tasks.Add(t);
not quite sure what u mean by waiting. Do you mean that you want something done (by the BW) after thats done you want to do something else? Use bw.RunWorkerCompleted like you do (use a seperate function for readability) and in that callback function do you next stuff. Start a timer to check if the work doesnt take too long.
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += (sender, args) =>
{
OnAsyncOperationCompleted(sender, args);
});
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
Timer Clock=new Timer();
Clock.Interval=1000;
Clock.Start();
Clock.Tick+=new EventHandler(Timer_Tick);
public void Timer_Tick(object sender,EventArgs eArgs)
{
if (bw.WorkerSupportsCancellation == true)
{
bw.CancelAsync();
}
throw new TimedoutException("bla bla bla");
}
In the OnDoWorkLoadChildren:
if ((worker.CancellationPending == true))
{
e.Cancel = true;
//return or something
}