19

I'm a C# newbie, so I'm struggling to understand some concepts, and I run into a piece of code that I'm not quite understanding:

static void Main(string[] args)
{
 Task.Run(async () => { await SomeClass.Initiate(new Configuration()); }).Wait();
 while (true) ;
}

As I understand, this runs a task which initiates a method. This method runs, and then, once it finished, it gets into an infinite loop waiting. It feels that either the code doesn't make sense, or that I'm not understanding right.

Jim G.
  • 15,141
  • 22
  • 103
  • 166
Pdon
  • 315
  • 1
  • 2
  • 5
  • 2
    It is forcing an async method `SomeClass.Initiate` to be executed synchronously. The Task.Run wrapping the async method is not needed. The infinite loop is to prevent the console window from closing immediately after completing `Initiate`. Where did this code come from, is there any context for it? – ndonohoe Sep 21 '16 at 17:25
  • There are better pieces of code to "run into" for running async methods in console app - http://stackoverflow.com/questions/17630506/async-at-console-app-in-c – Alexei Levenkov Sep 21 '16 at 17:37

3 Answers3

38

You can break this apart into several parts:

async () => { await SomeClass.Initiate(new Configuration()); }

Is a lambda expression that defines an async method that just awaits another method. This lambda is then passed to Task.Run:

Task.Run(async () => { await SomeClass.Initiate(new Configuration()); })

Task.Run executes its code on a thread pool thread. So, that async lambda will be run on a thread pool thread. Task.Run returns a Task which represents the execution of the async lambda. After calling Task.Run, the code calls Task.Wait:

Task.Run(async () => { await SomeClass.Initiate(new Configuration()); }).Wait();

This will block the main console app until the async lambda is completely finished.

If you want to see how it's broken out further, the following is roughly equivalent:

static async Task AnonymousMethodAsync()
{
  await SomeClass.Initiate(new Configuration());
}

static void Main(string[] args)
{
  var task = Task.Run(() => AnonymousMethodAsync());
  task.Wait();
  while (true) ;
}
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
6

I wrote a little .NET Fiddle that simply added some Console.WriteLine calls to hopefully help show you the order of execution.

The Task.Run returns a Task that represents an asynchronous operation, (a method that runs asynchronously). It's parameter in this situation is the Func<Task>. Your code has utilized the async and await keywords, as such your call to SomeClass.Initiate is an async lambda.

Queues the specified work to run on the thread pool and returns a proxy for the task returned by function.

All async code should return an awaitable, unless in the rare situation where you're authoring an event handler that needs to start some async calls.

The Task that is returned from the invocation of Task.Run is immediately invoking .Wait().

Waits for the Task to complete execution within a specified time interval.

That call to Task.Run is not needed, you could simply invoke .Wait() on the Task that is returned from the SomeClass.Initiate method.

As for the infinite loop, a console application exits immediately -- you could simply do the Console.ReadLine and wait for the user to hit the Enter key for example.

David Pine
  • 23,787
  • 10
  • 79
  • 107
2

Most likely SomeClass.Initiate is synchronous method marked async for no reason. Than someone tried to make it really run asynchronously and added Task.Run to run it on separate thread. But since it is console application - added .Wait() to wait for the operation to finish.

And while (true) ; is there because when running in VS console app closes without trace when it is done, more obvious way - add Console.ReadLine() call. while(true) is not realated to async portion at all as code will not leave .Wait() call before operation is done.

Another possibility is author was experimenting with async and did not have .Wait() or .Result - thus while(true) would give chance for operation to finish.

See async at console app in C#? for proper way to run async code in console app (just .Wait() or .Result)

Community
  • 1
  • 1
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179