EventStore/EventStore — pull request #254 by jen20 (2014-09-27 03:50:38+00:00)
Title: Client threading

When dealing with operations in the client API it is very easy to reach
deadlock, especially with subscriptions, as a worker thread is
blocked waiting for an asynchronous result which can never be completed as
the response from the server would be processed by the *same* worker
thread.

Instead dispatch these to the threadpool, which makes the following code
snippets:

```csharp
...
connection.Connected += OnConnected;
connection.ConnectAsync().Wait();
...

private static async void OnConnected(object sender, ClientConnectionEventArgs e)
{
var connection = e.Connection;
Console.WriteLine("-- Connection {0} CONNECTED", connection.ConnectionName);

await connection.SubscribeToStreamAsync(_statsStreamName, false,
(s, resolved) => Console.WriteLine("Event appeared: {0}@{1}", resolved.OriginalEventNumber, resolved.OriginalStreamId),
(s, r, ex) => Console.WriteLine("Subscription dropped: {0} (Exception message: {1})", r, string.IsNullOrWhiteSpace(ex.Message) ? "None" : ex.Message)
);
}
```

and

```csharp
...
connection.Connected += OnConnected;
connection.ConnectAsync().Wait();
...

private static void OnConnected(object sender, ClientConnectionEventArgs e)
{
var connection = e.Connection;
Console.WriteLine("-- Connection {0} CONNECTED", connection.ConnectionName);

connection.SubscribeToStreamAsync(_statsStreamName, false,
(s, resolved) => Console.WriteLine("Event appeared: {0}@{1}", resolved.OriginalEventNumber, resolved.OriginalStreamId),
(s, r, ex) => Console.WriteLine("Subscription dropped: {0} (Exception message: {1})", r, string.IsNullOrWhiteSpace(ex.Message) ? "None" : ex.Message)
).Wait();
}
```

behave in the same way, which is likely to be what is expected by users.

This change has not yet been tested for performance implications (I'm on a
flight and don't have anything sufficiently fast available) and it is
conceivable that there are other ways of preventing the deadlock (perhaps
selectively dispatching by the type of request).