Home > Back-end >  Best way to cancel long running process inside backgroundworker
Best way to cancel long running process inside backgroundworker

Time:04-29

What is the best solution to quickly cancel long running processes inside background worker? For example, we have such situation:

        private void DoWork(object sender, DoWorkEventArgs e)
        {
            ...

            for (int i = 0; i < items; i  )
            {
                if (_worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    VeryLongRunningProcess();
                }
            }
        }
        
        private void VeryLongRunningProcess()
        {
            var a = Test();
            var b = Test2();
            Thread.Sleep(5000);
            var c = Test3();
        }

In such case, VeryLongRunningProcess() will be not finished on pressing cancel until he finished everything inside his body.

What to do in such cases?

I tried to pass (BackgroundWorker)sender to VeryLongRunningProcess() as param and inside this method check for CancellationPending, but i dont know is this correct way or not

CodePudding user response:

If the problem is isolated your VeryLongRunningProcess from classes like the worker, you can use a Func as a parameter and leave outside your method the worker access

private void VeryLongRunningProcess(Func<bool> isCancelled)
{
    var a = Test();

    if (isCancelled())
    {
        return;
    }

    var b = Test2();

    if (isCancelled())
    {
        return;
    }

    Thread.Sleep(5000);
    var c = Test3();
}

Inside your method, you may check if you must cancel the operation as many times you need. And you can use the Func as a parameter in other methods like Test1, Test2... if any of them takes long time to finish.

Then, you invoke your method in this form:

VeryLongRunningProcess(() => _worker.CancellationPending);

As other people comment, maybe interesting use async/await.

UPDATE

Another way to do if you want choose the use or not of the cancellation:

private void VeryLongRunningProcess(Func<bool> isCancelled = null)
{
    var a = Test();

    // Or: isCancelled != null && isCancelled()
    if (isCancelled?.Invoke() ?? false)
    {
        return;
    }

    // ...
}

CodePudding user response:

Normally you should create long-running process as "async" method (public async Task or Task DoWork()) for resources destribution purposes. "CancelationToken" enables cooperative cancellation between threads, thread pool work items. Also it is possible to propagate a callback delegate that can be invoked when Cancellation Token cancelled or function is compleete.

  • Related