0

I have this simple code

static string ParentMethod()
{
1    var response = ChildMethod("param1")
2    string value = response.Result;
3
4    return value;
}

static async Task<string> ChildMethod(string param1)
{
1    string value = "";
2
3    var response = await Task.Run(() => SomeAPIDLL.SendSsMessage(param1));
4
5    if (response.RestExcpetion != null)
6       value = response.RestException.Message;
7
8    return value;
}

Not sure why but on the ChildMethod, after the Task.Run the debugger immediately points back to ParentMethod line 2 where at that point it executes the call (since I get a text message) but then never reads the Result and hangs in nowhere-lands, the client hangs, VS never recovers and I have to stop the Debugging to return to normal.

Is the problem the fact that if I have a ChildMethod Async, I have to MARK all parent calling methods Async too, all the way till the API public method?

Johnny
  • 601
  • 6
  • 18
  • There are a million other duplicates as well, just search on "await deadlock". – Servy Nov 13 '13 at 18:59
  • 2
    Don't use `Task.Result`. Instead, make everything async. – SLaks Nov 13 '13 at 18:59
  • 1
    "Is it the problem the fact that if I have a ChildMethod Async, I have MARK all parent calling methods Async too all the way till the API public method?" Pretty much. You do need to "async all the way up". That said, it's about *making the methods actually be asynchronous*, not strictly marking them as `async`. Using the `async` keyword is just one way of making a method asynchronous. – Servy Nov 13 '13 at 19:05
  • @SLaks the SomeAPIDLl is not Async so I cannot run it as Async if that's what you meant – Johnny Nov 13 '13 at 19:05
  • @Johnny Then there's not much point in leveraging asynchrony here. Just do everything synchronously. – Servy Nov 13 '13 at 19:06
  • @Servy Gotcha ...so that means that I will have to change all parent mathods to Task then, right? – Johnny Nov 13 '13 at 19:07
  • @Johnny Yes, you will – Servy Nov 13 '13 at 19:07
  • 2
    Also if you are making a API of your own to wrap SomeAPIDLL you should take a read of the MSDN blog post "[Should I expose asynchronous wrappers for synchronous methods?](http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx)" (the short version, "no, your should not"), I would just leave `ChildMethod` synchronous and then perhaps call `ParentMethod` in a asynchronous way if that would be beneficial to me as a consumer of your API (assuming `ParentMethod` is a exposed method in your API). – Scott Chamberlain Nov 13 '13 at 19:25
  • well, you're not forced to make it async all the way up. you can use an callback to return your string. but making parent async seems a better solution in this case – Fabio Marcolini Nov 13 '13 at 19:33
  • @ScottChamberlain that's an interesting point but I was under the impression that in order to make an API async, one has to "async" the method that might be slow (ie the 3rd party call of ChildMethod). Following your advise, how can I make the Parent async while leaving the Chil synchronous? by using the Task.Run onthe Parent call? – Johnny Nov 13 '13 at 19:36
  • @Johnny it's not possible to make certain parts of an application synchronous and other parts asynchronous. I don't happen to agree with the advice that synchronous methods shouldn't be made asynchronous -- that seems just as barmy to me as saying we should just ignore background workers and do everything on a UI thread -- but it's certainly a big overhaul. If you want to utilize an async method, then all the methods calling it must also be async. – Ben H Nov 13 '13 at 21:35
  • @ScottChamberlain I agree with you and yes it's a major overall if I really have to change all the levels that call that ChildMethod. Thanks for the advice !! – Johnny Nov 13 '13 at 22:29
  • @BenH I am not saying synchronous methods shouldn't be made asynchronous, I am saying don't needlessly make asynchronous methods if you don't need to. If I am calling this code and I need to make `ParentMethod` run in the background I as the caller can do a `Task.Run(() => ParentMethod())`, it is not the job of the API to provide those wrappers, especially if all the wrapper is doing is a simple `Task.Run` and no non-trivial work is done before or after that call. – Scott Chamberlain Nov 13 '13 at 22:34

0 Answers0