4

Suppose I have this (heavily redacted) function written in C# to run on .NET 6.

string DoThing(string myParam)
{
    /* Pre-processing redacted. */
    var resultOfGet = await xyz.GetAsync(thingToGet);
    /* Post-processing redacted. */
    return processedThing;
}

This fails with an error

The await operator can only be used within an async method

I've found similar questions on this site with this exact error and and the answer is almost uniformly to change the function signature to async and return a Task value.

This won't work for me. I don't want to send await calls up the chain, I need my function to take a string parameter and return a string value. Is there a way to call an async function as if it were a regular function?

Answering anticipated questions...

  • Does the library you're using have a non-async Get alongside GetAsync?
    Alas, no.

  • Why don't you want to your function to be async?
    It would break something else.

  • You should fix the "something else" then.
    This isn't an "XY" question. I could take you by the hand and show you what I'm doing, but we're only ever going to end up needing to wait for an async function to finish and get the results.

  • This question is a duplicate.
    If so, that's great, but please check there's an answer that doesn't approximate adding async to the calling function. If it doesn't, I'm asking a very different question.

  • Doesn't the Task object returned have a member function to wait for the result and return it?
    If it does, I couldn't find it. The name of that function would make a great answer to my question.

  • If the function is written as async it'll block the calling thread if you do wait for the result the way you want to.
    I am 100% happy to do that and willing to accept all responsibility for my decision.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
billpg
  • 3,195
  • 3
  • 30
  • 57
  • 3
    `var resultOfGet = xyz.GetAsync(thingToGet).Result;` -- the Result property will synchronously wait for the Task to complete. – Ben Voigt Jul 03 '23 at 20:34
  • There are none so blind... Thank you @BenVoigt. If you want to make that an answer I'll send you a green-tick. – billpg Jul 03 '23 at 20:36
  • Just be aware that the `GetAsync()` probably needs continuation code and/or event handlers to run on the calling thread, and when you block the calling thread those will not run and you will wait forever (deadlock). Possible solution is `Task.Run(() => xyz.GetAsync(thingToGet)).Result` which will provide the `GetAsync` with a synchronization context not bound to your own thread. – Ben Voigt Jul 03 '23 at 20:36
  • I think in my head I saw Result on the drop-down list and figured I would need to call Wait first and "dag nabbit why isn't there a WaitAndResult?". Maybe if I hadn't spent all that time trying to pre-empt someone with an "XY" response I'd have realised what I wanted was right there. – billpg Jul 03 '23 at 20:45
  • 2
    Also see my article on [brownfield async](https://learn.microsoft.com/en-us/archive/msdn-magazine/2015/july/async-programming-brownfield-async-development?WT.mc_id=DT-MVP-5000058). However, note that _every single workaround_ has some scenario where _it does not work_, and there are some scenarios where _no_ workaround work. So - in the _general_ case - the recommended answer is still "don't"; the workarounds are only for specific scenarios. – Stephen Cleary Jul 03 '23 at 20:54
  • `.GetAwaiter().GetResult()` is your friend. See [this](https://stackoverflow.com/questions/40324300/calling-async-methods-from-non-async-code/40329285#40329285) answer by usr. – Theodor Zoulias Jul 03 '23 at 21:09
  • Look at example ini https://dotnetfiddle.net/jdshTr – Ihdina Jul 04 '23 at 02:03

0 Answers0