4

I'm working on WCF client app, and I facing difficulties with the await/async pattern. It seems that the line: await client.LongOperationAsync(); always blocks. As I understand, the thread supposed to exit and continue on to the Main() method and then return when the async method completes, maybe I'm wrong.

The output for the code below is (always):

Test() started
Test() error
*
*
*
...

The Test() method always completes before the context returns to main. Any thoughts would be highly appreciated.

static void Main(string[] args) { Program p = new Program(); p.Test(); while (true) { Console.WriteLine("*"); Thread.Sleep(500); } } private async Task Test() { Console.WriteLine("Test() started"); try { MySoapClient client = new MySoapClient( new BasicHttpBinding(new BasicHttpSecurityMode()), new EndpointAddress("http://badaddress")); await client.LongOperationAsync(); Console.WriteLine("Test() success"); } catch (Exception) { Console.WriteLine("Test() error"); return; } Console.WriteLine("Test() end successfully"); } 

2
  • 1
    Keep in mind that you shouldn't depend on the order of code executing in a case like this. Since you're not waiting for your Test method to complete, you can't guarantee whether it will complete before or after any subsequent lines of code in the calling method. Commented Nov 9, 2013 at 2:12
  • Therefore it's not considered an error for it to complete in the order that it did. Commented Nov 9, 2013 at 2:13

1 Answer 1

4

Async methods execute synchronously until the first await; if your LongOperationAsync method performs a blocking operation before its first await, the calling method will be blocked as well. I suspect that's what happening in your case.

This is probably because WebRequest.BeginGetResponse performs some of its work synchronously. See Stephen Toub's answer to this question:

The Async CTP's GetRequestStreamAsync and GetResponseAsync are simple wrappers around the existing HttpWebRequest.BeginGetRequestStream and BeginGetResponse in .NET 4. Those Begin* methods have a lot of setup work they do (e.g. proxy, DNS, connection pooling, etc.) before they can submit a request, and unfortunately today that work all happens synchronously as part of the Begin* call.

In this case, you provided a bad domain name, so I suspect it takes a while for the DNS resolution to fail.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for responding Thomas. I think that this is indeed the case. This seems like a very poor behavior from the WCF proxy. This pretty much makes directly using WCF proxy from UI application impossible, right? Are there any other proxies out there that have 'true' async API?
@AdamLevi, well, it's not impossible, but if you want to make sure it never blocks, you have to do it in a separate thread... But I agree, it sucks. AFAIK, all proxy implementations would eventually call WebRequest.BeginGetResponse, so they would all suffer from the same problem. However, you could probably use the async methods in the Dns class to detect beforehand that the domain doesn't exist.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.