42

I have created task function for validating my json file. Everything works fine until I didn't use the result. When I am trying to get the result from async task<bool> function it is showing error as Cannot implicitly convert 'void' to bool. My async function is as follows:

 private async Task<bool> MyValidationFunction(string json)
 {
     bool isValid = true;
     .......DOING MY VALIDATION STUFF.....
     return isValid;
 }

Calling this function from another function is as follows:

 public bool GetJsonAndValidate()
 {
      bool isValid = true;
      string jsonData = GetJson();
      //******* Here I am getting the error.
      bool isValid = MyValidationFunction(jsonData).Wait(); 
 }

When I am trying to call MyValidationFunction it is showing error as mention above. I have tried to get result by using Result property but it is throwing and error. My Class is just simple public class. I can do it with synchronous call but I need to have asynchronous call as MyValidationFunction get the result from database. If I didn't use the bool variable to capture the result, then it works fine. What I have missed out? How can I get bool result from my validation function?

halfer
  • 19,824
  • 17
  • 99
  • 186
Iswar
  • 2,211
  • 11
  • 40
  • 65
  • what about `= await My...` – Lei Yang Jul 17 '17 at 07:28
  • 1
    Do not mix up `async` and `.Wait()` - it still blocks the thread and kills the idea of async/await. It also causes deadlock. If you use `async`, then use `await`. – Yeldar Kurmangaliyev Jul 17 '17 at 07:28
  • 2
    Once you start using `async`, you'll tend to find that it (most naturally) propagates up the call stack. The most natural thing to do here would be to make `GetJsonAndValidate` `async` also, and `await` the result from your validation function. – Damien_The_Unbeliever Jul 17 '17 at 07:29
  • @Damien_The_Unbeliever in that case other function which is calling GetJsonAndValidate should also be async right? – Iswar Jul 17 '17 at 07:32

3 Answers3

71

Statement 1. .Wait() has no return result. It is a void method, and therefore its result cannot be assigned to a variable.
You can use .Result which will wait until Task completes and return a result.

// Both are applicable to simple Tasks:
bool isValid = MyValidationFunction(jsonData).Result;

// does that same as

var task = MyValidationFunction(jsonData);
task.Wait();  
bool isValid = task.Result;

However, it is all valid for usual Tasks, but not for async/await functionality, because...

Statement 2. Do not mix up async and .Wait() - it still blocks the thread, killing the idea of async/await and negating all the performance improvement.

It also causes deadlock in WinForms, WPF, ASP.NET and other environments with SynchronizationContext. Read more about it in this Stephen Cleary's article or in these StackOverflow questions:

Simple rule: if you use async, then you use await.

// That's how you do it with async/await:
public async bool GetJsonAndValidate()
{
     string jsonData = GetJson();
     bool isValid = await MyValidationFunction(jsonData); 
}

It will not block the thread and enable asynchronous behavior.

Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101
  • Thank you @Yeldar Kurmangaliyev for your solution. I have mixed `.Result` with `.Wait()`. It works fine. – Iswar Jul 17 '17 at 07:35
  • @IswarKChettri It is nice if it works for you, but please pay attention to the second part of my answer to avoid problems in future :) – Yeldar Kurmangaliyev Jul 17 '17 at 07:40
  • 1
    yes, sure I will pay attention to the second part as well for minimising error in future. Thank you so much. – Iswar Jul 17 '17 at 07:42
  • `Error CS1983 The return type of an async method must be void, Task, Task, a task-like type, IAsyncEnumerable, or IAsyncEnumerator` This is what I get when I try your last suggestion, how to overcome it ? – GuidoG Nov 25 '22 at 07:37
8

Change this:

bool isValid = MyValidationFunction(jsonData).Wait(); 

to

  bool isValid = MyValidationFunction(jsonData).Result; 

Task.Wait's return type is void. Task.Result does a wait and fetches the result from the task.

Not related to OP's question, but its bad idea to mix async and Wait(or Result). You may get weird hangs in your application because of deadlocks if your application depends on a SynchronizationContext

bashrc
  • 4,725
  • 1
  • 22
  • 49
5

I've been working with async methods and always used it this way :

bool isValid = await MyValidationFunction(jsonData);

I saw the provided answers.

Sometimes .Result dies. So, i would suggest you to use await instead of .Result.

Bob Swager
  • 884
  • 9
  • 25
  • Works like a charm, thanks for taking the time to share. – Abdelali Laaraje Jun 20 '21 at 05:10
  • it's kinda crazy the top answer is so verbose that I literally missed the actual answer hidden inside it, whereas this simply provides the one-liner we need... – pete Jun 07 '22 at 07:42