Ben Biddington

Whatever it is, it's not about "coding"

Posts Tagged ‘threading

Async operations and exceptions

leave a comment »

We have had the case where we’re creating a class that allows clients to block while internally it reads an entire stream asynchronously. This class encapsulates the state required to perform such a task.

While attempting to write unit tests for exceptions, we found that an exception thrown during the asynchronous operation would not be thrown to client. Debugging showed that the exception was being thrown, but no notification was being sent to the parent thread.

No such thing as unhandled exceptions on managed threads

[MSDN] [since .NET Framework v2.0] There is no such thing as an unhandled exception on a thread pool [or finalizer] thread. When a task throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then returns the thread to the thread pool.

Errors raised on a child thread are essentially lost when the thread exits. This means there is some work required to propagate these exceptions.

This requires a blocking wait on the part of the client, and a mechanism for storing the exception so the parent thread can read it.

As an example, we have implemented an AsyncStreamReader which contains a blocking ReadAll method. If an asynchronous read fails with an exception, that exception is exposed internally as a field, and the waiting thread is then signalled. Once the waiting thread wakes up it checks the exception field and throws it if required.

We have blocking Read operation that waits for an async read to complete. The notification mechanism is a ManualResetEvent (WaitHandle).

  1. T1: Invoke ReadAll.
  2. T1: Start async operation (spawns T2).
  3. T1: Wait.
    1. T2: Async operation encounters exception.
    2. T2: Store exception in _error field.
    3. T2: Signals T1.
    4. T2: Returns without triggering any subsequent reads.
    5. T2: Thread exits
  4. T1: Parent thread resumes (still inside ReadAll).
  5. T1: Checks _error field. If it is not null, throw it, otherwise return.
  6. T1: Exception is now propagated

References

Advertisements

Written by benbiddington

27 April, 2010 at 13:37

Asynchronous operations, what is EndInvoke for?

leave a comment »

When an exception is thrown on a worker thread, it does not appear on the parent thread unless EndInvoke is called.

[MSDN, How to call a Visual C# method asynchronously] The EndInvoke() function is used to retrieve the results of the asynchronous call. It can be called anytime after BeginInvoke(). If the asynchronous call has not completed yet, EndInvoke() blocks until it completes. The parameters of the EndInvoke() function includes the out and ref parameters that the wrapped function has, plus the IAsyncResult object that is returned by BeginInvoke().

There are four common ways to use BeginInvoke() and EndInvoke() to make asynchronous calls. After you call BeginInvoke(), you can:

  • Optionally do some other work and then use EndInvoke().
  • Obtain a WaitHandle that is provided by the IAsyncResult object, use its WaitOnemethod to block until the WaitHandle is signaled, and then call EndInvoke().
  • Poll the IAsyncResult object to determine when the asynchronous call has completed, and then call EndInvoke().
  • Have the system call a callback function that you specify. This callback function calls EndInvoke() and processes the results of the asynchronous call when it completes.

Note: It is an error to call EndInvoke more than once for an async operation.

The recommendations for implementing IAsyncResult state that setting is as completed should do things in a specific order. And that order has setting the wait handle happening before the callback is invoked.

Here’s an example EndInvoke implementation:

public void EndInvoke() {
    if (false == IsCompleted) {
        AsyncWaitHandle.WaitOne();
        AsyncWaitHandle.Close();
        asyncWaitHandle = null;
    }

    if (exception != null) {
        throw exception;
    }
}

This is starting to make sense — EndInvoke is a way to force control back  to the parent thread, since it blocks until the async operation has completed before returning. This is why exceptions are thrown from here if they occur — control has returned to the master thread.

[EDIT: 13-Sep-2009] Also, .NET Framework 2.0+, unhandled exceptions are not propagated to parent threads, i.e., child threads exit gracefully.

Written by benbiddington

3 December, 2008 at 21:37

Posted in development

Tagged with ,