问题
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.
Thanks
回答1:
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) ;
}
回答2:
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.
回答3:
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
)
来源:https://stackoverflow.com/questions/39622528/understanding-the-use-of-task-run-wait-async-await-used-in-one-line