2

When I ran the following code (which I was asked during a C# interview), it did not output anything.

Can somebody explain this behavior?

class Program {
  private static string result;

  static void Main() {
    SaySomething();
    Console.WriteLine(result);
  }

  static async Task<string> SaySomething() {
    await Task.Delay(5);
    result = "Hello world!";
    return “Something”;
  }
}

I thought this method should output result, because I am calling

Console.WriteLine(result);

after the SaySomething() method call completed

whereisSQL
  • 638
  • 2
  • 13
  • 23
Jaganmohanreddy
  • 391
  • 4
  • 19
  • 8
    You're not waiting for `SaySomething` to finish. – juharr Aug 27 '15 at 19:03
  • 2
    You should know how await / async work if you are going to use it in your code. https://msdn.microsoft.com/en-us/library/hh191443.aspx – Igor Aug 27 '15 at 19:04
  • Your are executing `Console.WriteLine(result);` before your fire&forget task is executing the assignment. – Eser Aug 27 '15 at 19:07
  • @Igor He said it was an interview question, not that he's actively writing code using it. That said, it's still a good resource to read. – sab669 Aug 27 '15 at 20:04
  • @Igor I'm not much familiar with asynchronous programming. Any way the link you referred is good one to read. – Jaganmohanreddy Aug 27 '15 at 20:07

4 Answers4

2

Because SaySomething is async it will yield control of the thread to the caller when you hit the await Task.Delay(5) and thus hit the Console.WriteLine(result) before it changes the value of result. Just change it to SaySomething().Wait(); and it will work.

juharr
  • 31,741
  • 4
  • 58
  • 93
1

This program would have written something to console, if you had given the Task<string> enough time to complete. Currently, however, the program exists before SaySomething() finishes.

To fix this problem, make sure that you wait for the Task<string>:

static void Main() {
    MainAsync().Wait();
}
private static async Task MainAsync() {
    var retVal = await SaySomething().ConfigureAwait(false);
    Console.WriteLine("{0} - {1}", retVal, result);
}

Note that your current version also ignores the result returned by your asynchronous task. The example above stores the return value in retVal variable, and prints it along with the the result stored by SaySomething in the static variable.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

Your SaySomething() method is async. Your Console.WriteLine(results) is getting called before the task completed. You can do one of a couple of things.

You can call your function like this:

SaySomething().Wait();

Or you could break your process out like this:

private static string result;

    static void Main()
    {
        CallSaySomething();
        Console.WriteLine(result);
        Console.ReadLine();
    }

    static async Task<string> SaySomething()
    {
        await Task.Delay(5);
        result = "Hello world!";
        return "Something";
    }

    static string CallSaySomething()
    {
        var task = SaySomething();
        task.Wait();

        var result = task.Result;
        return result;
    }
CodeLikeBeaker
  • 20,682
  • 14
  • 79
  • 108
  • If i replace await Task.Delay(5); with await Thread.Sleep(5); then it will write "Hello world!". This is the point where i got confused. Can you explain why is it so ? – Jaganmohanreddy Aug 27 '15 at 19:20
  • @JaganMohanReddy take a look at this SO post to answer your question: http://stackoverflow.com/questions/20082221/when-to-use-task-delay-when-to-use-thread-sleep – CodeLikeBeaker Aug 27 '15 at 19:27
0

You are not waiting for the Task returned by SaySomething to complete. As soon as the await Task.Delay(5) runs the SaySomething returns to Main. At this point result as not been set, so Console.WriteLineprints an empty string. Then your application ends whenMainexits and the task started inSaySomething` never completes.

You want this instead:

class Program {
  private static string result;

  static void Main() {
    SaySomething().Wait();
    Console.WriteLine(result);
  }

  static async Task<string> SaySomething() {
    await Task.Delay(5);
    result = "Hello world!";
    return “Something”;
  }
}

In the normal case however you would want await SaySomething(); instead of blocking, but Main is not allowed to be an async method.

shf301
  • 31,086
  • 2
  • 52
  • 86