C# 任务。等待不';不要等待异步方法完成

C# 任务。等待不';不要等待异步方法完成,c#,.net,asynchronous,C#,.net,Asynchronous,代码如下: static async Task Main(string[] args) { var t = new Task(async () => await AsyncTest()); t.Start(); t.Wait(); Console.WriteLine("Main finished"); } private static async Task AsyncTest() { Thread.Sleep(2000); await Ta

代码如下:

static async Task Main(string[] args)
{
    var t = new Task(async () => await AsyncTest());
    t.Start();
    t.Wait();
    Console.WriteLine("Main finished");
}

private static async Task AsyncTest()
{
    Thread.Sleep(2000);
    await Task.Delay(2000);
    Console.WriteLine("Method finished");
}
我的期望是
t.Wait()
将实际等待
AsyncTest
方法完成,输出将是:

Method finished 
Main finished
实际上,输出只有
主完成
。Wait()就在您点击
Wait Task.Delay(2000)
inside AsyncTest时完成。如果将
t.Wait()

解决方案是将方法重写为同步实现或直接在AsyncTest()上调用Wait()。然而,问题是为什么它以如此奇怪的方式工作

另外,这是代码的简化版本。我试图实现延迟任务执行。实际上,任务对象是由程序的一部分创建的,然后在特定条件下由另一部分执行


UPD:将var
t=newtask(async()=>await AsyncTest())
重写为
var t=newtask(()=>AsyncTest().Wait())
也解决了这个问题。虽然我仍然不太明白为什么任务不能正确地使用async/await内部委托。

不要使用
var Task=new Task(…);task.Start(),只使用
任务。改为运行

在第一种情况下,使用构造函数
Task(Action-Action)
,所以实际上您并不等待异步方法。如果您检查
real
C#而不使用asyn wait syntax sugar,您将看到
asynchvoidmethodbuilder
。在
Task.Run
的情况下,您使用
Task.Run(Func-Func)
以接收“真实”任务

所以,如果你想使用构造函数,你应该使用注释中的方法:
newtask

A from@JonSkeet:

异步方法只返回void,这意味着没有简单的方法 等待它完成的任何事情。(你几乎应该总是 避免使用异步void方法。它们实际上只适用于 为了订阅活动。)

请看这行代码:

var t = new Task(async () => await AsyncTest());
查看
任务
构造函数的签名:

    public Task(Action action);
    public Task(Action action, CancellationToken cancellationToken);       
    public Task(Action action, TaskCreationOptions creationOptions);
    public Task(Action<object> action, object state);
    public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions);
    public Task(Action<object> action, object state, CancellationToken cancellationToken);
    public Task(Action<object> action, object state, TaskCreationOptions creationOptions);
    public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions);
检查这个

public static async Task Main(string[] args)
{
    var t = Task.Factory.StartNew(async () => await AsyncTest());
    //t.Start();
    t.Result.Wait();    
    t.Wait();
    Console.WriteLine("Main finished");
}

private static async Task AsyncTest()
{
    //Thread.Sleep(2000);
    await Task.Delay(2000);
    Console.WriteLine("Method finished");
}
还有这个

我仍然不太明白为什么任务不能在委托内部使用async/await正确工作

因为
任务
构造函数仅用于创建-即表示要运行的同步代码的任务。由于代码是同步的,因此您的
async
lambda将被视为
async void
lambda,这意味着
任务
实例不会异步等待
AsyncTest
完成

更重要的是。它几乎没有有效的用例

Task.Task
的一个很好的替代品是
Task.Run
,它可以理解
async
lambdas


在我的实际程序中,任务延迟了执行。任务对象在一个地方创建,然后在程序的另一部分执行特定条件之后创建

在这种情况下,请使用。具体来说,
Func

static async Task Main(字符串[]args)
{
Func Func=异步测试;
//等我们准备好跑步的时候。
等待函数();
控制台写入线(“主完成”);
}
专用静态异步任务AsyncTest()
{
《睡眠》(2000年);
等待任务。延迟(2000);
Console.WriteLine(“方法完成”);
}

不要使用
var task=新任务(…);task.Start(),只使用
任务。改为运行
。在我的实际程序中,任务已延迟执行。任务对象在一个地方创建,然后在程序的另一部分执行特定条件之后创建。可能重复@WiktorZychla的
AsyncTest
返回任务,但
async()=>wait AsyncTest()
lambda将其丢弃,因为它本身是一个
操作(
void
)<代码>()=>AsyncTest().Wait()
将“修复”它(由于
Wait()
),仍然会出错。);var t2=t1.Unwrap();t1.Start();t2.等待()这是如何回答这个问题的?虽然这个答案很有道理,但你似乎是从中复制了解释。@WiktorZychla是的,第一段来自legend JonSkeet,我最近编辑了答案,但离开了笔记本电脑,忘记了发送更改。问题是:为什么模式
var t=new Task(…);t、 等待()未按预期工作。
public static async Task Main(string[] args)
{
    var t = Task.Factory.StartNew(async () => await AsyncTest());
    //t.Start();
    t.Result.Wait();    
    t.Wait();
    Console.WriteLine("Main finished");
}

private static async Task AsyncTest()
{
    //Thread.Sleep(2000);
    await Task.Delay(2000);
    Console.WriteLine("Method finished");
}
static async Task Main(string[] args)
{
    Func<Task> func = AsyncTest;

    // Later, when we're ready to run.
    await func();
    Console.WriteLine("Main finished");
}

private static async Task AsyncTest()
{
    Thread.Sleep(2000);
    await Task.Delay(2000);
    Console.WriteLine("Method finished");
}