1

I created Backgroundworker to operate on serial port which uses some methods provided by different classes. I'd like to cancel a worker each time an exception from those methods occurs.

Actually, I have some idea how to do it, using events, but I am afraid it's not optimal solution or a good practice. In that case I should firing event in each method, which is not efficient in my opinion.

For ex., one from methods, ReceiveRecord looks like that:

public string ReceiveRecord()
{
    try
    {
        var receivedLine = _serial.ReadLine();
        return receivedLine;
    }
    catch (TimeoutException exception)
    {
        MessageBox.Show($"Error was occured: \r\n {exception.Message}", "Timeout error",
            MessageBoxButton.OK, MessageBoxImage.Error);
        // HERE i want to fire worker cancellation 

    }
    return String.Empty;
}

Worker calls that methods periodically.

I considered returning false, when errors occurs, but I don't have ANY idea, how to do it, if method returns string...

Are there any simple method to fire DoWork cancellation from the catch fragment of code?

Morpheus
  • 119
  • 1
  • 11
  • you can use `out bool` parameter or you can return null in case of exception or throw exception back to caller and check there in try catch to cancel it – Ehsan Sajjad Sep 28 '17 at 20:48
  • possible duplicate of [How to stop BackgroundWorker correctly](https://stackoverflow.com/questions/4732737/how-to-stop-backgroundworker-correctly) – oRole Sep 28 '17 at 20:53

2 Answers2

0

Don't catch the exception in the method. Let the caller handle it in BackgroundWorker's RunWorkerCompleted event.

See Background worker exception handling

digimunk
  • 14
  • 3
  • But does exception fire RunWorkerCompleted event? Does it throw unhandled exception during DoWork runs? – Morpheus Sep 28 '17 at 20:56
  • The thread aborts, and RunWorkerCompletedEventArgs is sent to the RunWorkerCompleted event with the .Error property set. From inside RunWorkerCompleted, throw an exception that contains the message from .Error. Please see the link in my answer. – digimunk Sep 28 '17 at 21:01
  • Ok, I used events so far, but you clear that to me, so I implement it later. BTW, I used to catch all exceptions in methods, as fast, as I could, cause I thought it will be safer. – Morpheus Sep 28 '17 at 21:17
0

The BackgroundWorker class has a WorkerSupportsCancellation boolean which tells the worker whether the worker supports cancellation or not. Enable this then in your backgroundworker DoWork event, check if CancellationPending, if true, end the thread, otherwise continue with normal operation.

Use the CancelAsync() function to set cancellation pending true. You would want to set this in your catch block.

In my example below, my background worker is in a while loop, but it should give you the right idea.

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        while (true)
        {
            if (bw.CancellationPending)
                break;

            do_state_machine();
            Thread.Sleep(100);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
Baddack
  • 1,947
  • 1
  • 24
  • 33