8

I am trying to create a SignalR application using the C# 5 async/await features, but whenever the code is run, it will throw an System.InvalidOperationException. Here is the simplest code to reproduce the problem.

public class SampleHub : Hub
{
    public Task<string> GetGoogle()
    {
        var http = new WebClient();
        return http.DownloadStringTaskAsync("http://www.google.com");
    }
}

Exception details:

An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async=\"true\" %>.

Stack trace:

at System.Web.AspNetSynchronizationContext.OperationStarted()
at System.Net.WebClient.DownloadStringAsync(Uri address, Object userToken)
at System.Net.WebClient.DownloadStringTaskAsync(Uri address)
at System.Net.WebClient.DownloadStringTaskAsync(String address)

On the client side, the Javascript looks like this.

$.connection.hub.start().done(function () {
    $('#google').click(function () {
        var google = sample.server.getGoogle();
        console.log(google);
    });
});

What did I do wrong? Are there any workarounds? I am really keen to stick to the async/await patterns in C# if possible at all.

svick
  • 236,525
  • 50
  • 385
  • 514
Adrian So
  • 148
  • 1
  • 5

1 Answers1

10

I would try replacing WebClient with HttpClient. The DownloadStringTaskAsync is a kind of "bolt-on" support for async over the existing EAP methods, and it's the EAP methods that SignalR is objecting to. HttpClient uses TAP directly.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Thank you so much! I spent 2 nights trying to get that working, and it never strike me that the good old WebClient was the culprit. – Adrian So May 06 '13 at 22:17