I've created a backgroundworker to load data from a file. So far it works as intented but when I try to add a way to cancel the operation it doesnt work however I try. For testing I've broken the logic down to miminum but the result stays unchanged. I also confirmed, that the backgroundworker and the caller are not operating on the same thread.
Initialization of the Worker (inside of the class FileLoader):
private BackgroundWorker Worker = new BackgroundWorker();
private ManualResetEvent WorkerDone = new ManualResetEvent(false);
public FileLoader()
{
Worker.WorkerSupportsCancellation = true;
Worker.DoWork += Worker_DoWork;
Worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
}
public void LoadAsync() => Worker.RunWorkerAsync();
public void CancelLoad()
{
if (!Worker.IsBusy) return;
WorkerDone.Reset();
Worker.CancelAsync();
WorkerDone.WaitOne();
}
Worker Functions:
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
object data = new object();
Thread.Sleep(5000);
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
e.Result = data;
}
private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
Console.WriteLine("Cancel requested");
WorkerDone.Set();
}
else LoadCompleted?.Invoke(this, e.Result);
}
If no cancel is requested the worker operates as expected and Worker_RunWorkerCompleted
is called. But when a cancel is requested Worker_DoWork
is terminated and e.Cancel
is set to true but Worker_RunWorkerCompleted
is never called in any way and the cancel operation freezes.
According to the documentation of Backgroundworker the RunWorkerCompleted
event should always fire when the assigned function ends regardless of an cancel or not.