0

What is the difference between these two methods, they compile differently but you can call both of them in the same way with the await keyword. I am wanting to use these for defining my WCF interfaces with an await keyword on Entity Framework 6.1.

Just interested which of these two methods is more correct for the use over WCF, im using a service factory host (no add service reference) so do not get the generated async methods.

    public static Task<string> MethodA()
    {
        Console.WriteLine("{0} - Running MethodA on thread {1}", DateTime.Now, System.Threading.Thread.CurrentThread.ManagedThreadId);
        var task =  Task.Run(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.WriteLine("{0} - Done MethodA on thread {1}", DateTime.Now, System.Threading.Thread.CurrentThread.ManagedThreadId);
            return string.Format("You ran MethodA on thread {0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
        });
        Console.WriteLine("{0} - MethodA Returning on thread {1}", DateTime.Now, System.Threading.Thread.CurrentThread.ManagedThreadId);
        return task;
    }

    public static async Task<string> MethodB()
    {
        Console.WriteLine("{0} - Running MethodB on thread {1}", DateTime.Now, System.Threading.Thread.CurrentThread.ManagedThreadId);
        var task = Task.Run(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.WriteLine("{0} - Done MethodB on thread {1}", DateTime.Now, System.Threading.Thread.CurrentThread.ManagedThreadId);
            return string.Format("You ran MethodB on thread {0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
        });
        Console.WriteLine("{0} - MethodB Returning on thread {1}", DateTime.Now, System.Threading.Thread.CurrentThread.ManagedThreadId);
        return await task;
    }

To provide some more info on this, after reading all the responses you are correct. the difference is in the state generation so I guess if we are not going to be using the state the first method is more correct.

below is the de-compiled code

public static Task<string> MethodA()
{
  Console.WriteLine("{0} - Running MethodA on thread {1}", (object) DateTime.Now, (object) Thread.CurrentThread.ManagedThreadId);
  if (Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegatea == null)
  {
    // ISSUE: method pointer
    Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegatea = new Func<string>((object) null, __methodptr(\u003CMethodA\u003Eb__9));
  }
  Task<string> task = Task.Run<string>(Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegatea);
  Console.WriteLine("{0} - MethodA Returning on thread {1}", (object) DateTime.Now, (object) Thread.CurrentThread.ManagedThreadId);
  return task;
}

public static Task<string> MethodB()
{
  Program.\u003CMethodB\u003Ed__d stateMachine;
  stateMachine.\u003C\u003Et__builder = AsyncTaskMethodBuilder<string>.Create();
  stateMachine.\u003C\u003E1__state = -1;
  stateMachine.\u003C\u003Et__builder.Start<Program.\u003CMethodB\u003Ed__d>(ref stateMachine);
  return stateMachine.\u003C\u003Et__builder.Task;
}

[CompilerGenerated]
private static void \u003CMain\u003Eb__0()
{
  Program.CallServices();
}

[CompilerGenerated]
private static string \u003CMethodA\u003Eb__9()
{
  Thread.Sleep(TimeSpan.FromSeconds(2.0));
  Console.WriteLine("{0} - Done MethodA on thread {1}", (object) DateTime.Now, (object) Thread.CurrentThread.ManagedThreadId);
  return string.Format("You ran MethodA on thread {0}", (object) Thread.CurrentThread.ManagedThreadId);
}

[CompilerGenerated]
private static string \u003CMethodB\u003Eb__b()
{
  Thread.Sleep(TimeSpan.FromSeconds(2.0));
  Console.WriteLine("{0} - Done MethodB on thread {1}", (object) DateTime.Now, (object) Thread.CurrentThread.ManagedThreadId);
  return string.Format("You ran MethodB on thread {0}", (object) Thread.CurrentThread.ManagedThreadId);
}
Robert Brown
  • 109
  • 3
  • are you familiar with asych calls and when and why to use them.. if you are wanting to process something immediately then don't use asynchronous processing / calls otherwise if you are waiting for the process to complete then use async – MethodMan Jan 22 '15 at 20:40

2 Answers2

1

The former will return a "hot task", meaning it wont wait for completion of the Task.

The latter will asynchronously wait for the operation to complete while yielding control to the caller and resuming once finished, which will then return the completed task to the caller. It will also generate a state-machine under the covers which is responsible for the invocation of the tasks continuation.

If you're not doing anything with the returned value from the async operation, use the former. Also, there's the difference in excepion handling

As a side note, exposing async wrappers over sync methods isn't recommended. Instead, call the synchronous method explicitly.

Community
  • 1
  • 1
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
0

There's no difference whatsoever in the functionality of these options. The only difference is that GetData1 is an async method (which comes at the cost of building the async state machine) while GetData isn't. This can add a very slight overhead.

The difference usually between an async method and simply returning a Task is that the async method stores any exception inside the returned task while the other doesn't. In your case, since all these methods do nothing before returning a Task there's no chance for an exception and so they behave similarly.

As long as you understand what's going on, since GetData has slightly better performance it's the better option.

i3arnon
  • 113,022
  • 33
  • 324
  • 344
  • 1
    Slight performance advantage for this single operation, but on heavily used system will be a disadvantage (if the operation has I/O, not simple debugging method). – Erik Philips Jan 22 '15 at 20:47
  • I did update my comment, down and dirty is that if the `async` method calls an I/O then the system (OS) can re-purpose that thread (statemachine) and use that thread for another request. The long read is [MSND - Synchronous and Asynchronous I/O](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365683%28v=vs.85%29.aspx). – Erik Philips Jan 22 '15 at 20:52
  • 1
    @ErikPhilips That's not relevant at all here. Whether you `await` the `Task` or just return it directly without making the method `async` isn't going to have any impact on performance. The only difference is whether any exceptions would be wrapped in the `Task` or thrown to the caller. – Servy Jan 22 '15 at 20:53
  • @ErikPhilips I'm not sure what you're trying to say. `Task.Run` can `await` any kind of `async` operation, but it's irrelevant whether `GetData` returns the task directly or not. – i3arnon Jan 22 '15 at 20:54
  • @Servy I'm missing something, he's specifically asking about these two method in the context of WCF. Granted these two methods as written are exactly as I3arnon mentioned, but looking at the entire eco-system (WTF->Entity Framework) and in terms of using real code, there can be a significant difference. – Erik Philips Jan 22 '15 at 20:58
  • 1
    @ErikPhilips The only differences between these two methods, even in the general case, are that exceptions are handled differently, and one creates a state machine who's functionality isn't actually needed. That's it. – Servy Jan 22 '15 at 21:01
  • @ErikPhilips A signification difference **in favor** of the redundant `async` method? – i3arnon Jan 22 '15 at 21:01
  • Ok I give up. I'd prefer the OP know more about how it would be in the real world using real methods. That is obviously not the case in these comments. – Erik Philips Jan 22 '15 at 21:02