Yes, you may have a problem with Execute
. It can leave a file
unprocessed by your worker
.
You can solve it in two ways:
1) Your worker
doesn't finish after processing all queued files. It waits on a AutoResetEvent
for next file to process. In that case Execute
should notify the worker
by calling AutoResetEvent.Set
.
Example:
AutoResetEvent event;
...
// in worker_DoWork
while(!worker.CancellationPending){
event.WaitOne();
// Dequeue and process all queued files
}
...
// in Execute
fileQueue.Enqueue(file);
event.Set();
2) Your worker finishes after processing all queued files (as you do now) but you can check in BackgroundWorker.RunWorkerCompleted
whether there are still files to process and run the worker once again.
In that case if Execute
hasn't started the worker
because it was busy then the worker
will be started again in BackgroundWorker.RunWorkerCompleted
and the pending file
will be processed.
// in worker_RunWorkerCompleted
if (!fileQueue.IsEmpty())
Start();
Note: if you decide to use BackgroundWorker.RunWorkerCompleted
in a non-GUI application then you should be careful in Start
because BackgroundWorker.RunWorkerCompleted
can be invoked not on the thread where you call Execute
and a race condition will occur in Start
. More info: BackgroundWorker.RunWorkerCompleted and threading
if you call Start()
from two different threads simultaneously then they both can see that worker.IsBusy == false
and they both will call worker.RunWorkerAsync()
. The thread which calls worker.RunWorkerAsync()
a little later than another thread will throw an InvalidOperationException
. So you should catch that exception or wrap IsBusy
+RunWorkerAsync
into a critical section with a lock to avoid the race condition and the exception throwing.