1

I have two code section in both of them I'm trying to use Func<Task>. Can anyone point out the difference between below two code sections. Which approach should I follow.

static void Main(string[] args)
{
    Func<Task<int>> getter = async () => await Get();

    int x = getter().Result;

    Console.WriteLine("hello : " + x);
}
        
static async Task<int> Get()
{
     await Task.Delay(1000);
     return 1;
}

static void Main(string[] args)
{
     Func<Task<int>> getter = () => Get();

     int x = getter().Result;

     Console.WriteLine("hello : " + x);
}
        
static async Task<int> Get()
{
      await Task.Delay(1000);
      return 1;
}
ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
Pulkit Sharma
  • 390
  • 2
  • 14

2 Answers2

2

The difference is a stacktrace in case of errors. If you modify the code a bit as following, you would see how results differ.

internal class Example1
{
    public static void Main(string[] args)
    {
        Func<Task<int>> getter = async () => await Get();

        int x = getter().Result;

        Console.WriteLine("hello : " + x);
    }

    static async Task<int> Get()
    {
        throw new Exception("test");
        await Task.Delay(1000);
        return 1;
    }
}

internal class Example2
{
    public static void Main(string[] args)
    {
        Func<Task<int>> getter = () => Get();

        int x = getter().Result;

        Console.WriteLine("hello : " + x);
    }

    static async Task<int> Get()
    {
        throw new Exception("test");
        await Task.Delay(1000);
        return 1;
    }
}

When Example1 throws the exception, you see a stacktrace as following. Looking at the stacktrace, you know that the Get() method was called from the anonymous method.

This exception was originally thrown at this call stack:
    StackOverflow.CSharp.Example1.Get() in Example.cs
    StackOverflow.CSharp.Example1.Main.AnonymousMethod__0_0() in Example.cs

However, when Example2 throws the exception, the stacktrace is reduced and does not show where Get() was called from. It could be hard to trace a potential problem.

This exception was originally thrown at this call stack:
    StackOverflow.CSharp.Example2.Get() in Example.cs

In our projects, we prefer the first approach with async/await.

Evgeny Shmanev
  • 771
  • 6
  • 11
0

For a trivial case like this both examples will do more or less the same thing.

As a rule of thumb you should return the task directly without awaiting where you can. I.e. in cases where you call a single method that returns a task and do not do any processing of the result. But this is mostly for code style reasons, i.e. avoiding unnecessary keywords that might confuse a reader. So example 2 would be preferred.

Ofc. In your specific example you should probably not use async at all, and prefer Thread.Sleep. In a UI program you should avoid using .Result, since it will block the UI thread, and increases the risk of deadlocks.

JonasH
  • 28,608
  • 2
  • 10
  • 23