为什么我的 TCS 不等待?
Why does my TCS not await?
async
关键字do导致CIL改变(即使方法内部没有await),但它主要是为了让await
出席。
但我没想到会发生以下情况:
static void Main(string[] args)
{
Task t = Go();
t.Wait();
}
static async Task Go()
{
Console.WriteLine(1);
await AAA(3000);
Console.WriteLine(2);
}
static Task<object> AAA(int a) // <--- No `async`
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Task.Delay(a).ContinueWith(b => tcs.SetResult(null));
return tcs.Task;
}
这个打印:
1
(wait)
2
但是如果我改变
static Task<object> AAA(int a)
至
static async Task<object> AAA(int a)
它打印:
1
2
(no wait)
问题
为什么我看不到延迟? TCS 仅在三秒后解析。同时任务未解决,等待中
因为当你 return Task
来自一个 return 类型 Task<object>
的异步方法时,你会 Task<Task>
通过你的任务(即您希望在里面等待)。那你应该做什么:
static async Task<object> AAA(int a)
{
await Task.Delay(a);
return null;
}
简而言之,尽量避免在一种方法中混合使用异步等待和直接任务操作。
如果没有 async
关键字,您将从 AAA
返回 TaskCompletionSource
的任务,因此您等待它完成(这将在延迟完成后发生)。
但是,当您添加 async
关键字时,该方法返回的任务是同步完成的状态机任务。该任务包含(因此)TaskCompletionSource
的任务,但这不是您正在等待的任务。
如果您希望该方法等待 TaskCompletionSource
的任务,您可以等待 Task<Task>
的内部任务:
await ((Task) await AAA(3000));
或者等待 TaskCompletionSource
而不是返回它:
async Task AAA(int a)
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Task.Delay(a).ContinueWith(b => tcs.SetResult(null));
await tcs.Task;
}
或者更好,只是等待 Task.Delay
本身:
async Task<object> AAA(int a)
{
await Task.Delay(a);
return null;
}
如 Serg 所述,请查看 Visual Studio 中的示例:
static async Task<int> AAA(int a) // <--- No `async`
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
Task.Delay(a).ContinueWith(b =>
{
tcs.SetResult(1);
});
return tcs.Task;
}
你会得到这样的错误:
由于这是一个异步方法,return 表达式的类型必须是 'int' 而不是 'Task',因为您的方法将运行 同步。这就是为什么需要 return int
,而不是 Task
.
async
关键字do导致CIL改变(即使方法内部没有await),但它主要是为了让await
出席。
但我没想到会发生以下情况:
static void Main(string[] args)
{
Task t = Go();
t.Wait();
}
static async Task Go()
{
Console.WriteLine(1);
await AAA(3000);
Console.WriteLine(2);
}
static Task<object> AAA(int a) // <--- No `async`
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Task.Delay(a).ContinueWith(b => tcs.SetResult(null));
return tcs.Task;
}
这个打印:
1
(wait)
2
但是如果我改变
static Task<object> AAA(int a)
至
static async Task<object> AAA(int a)
它打印:
1
2
(no wait)
问题
为什么我看不到延迟? TCS 仅在三秒后解析。同时任务未解决,等待中
因为当你 return Task
来自一个 return 类型 Task<object>
的异步方法时,你会 Task<Task>
通过你的任务(即您希望在里面等待)。那你应该做什么:
static async Task<object> AAA(int a)
{
await Task.Delay(a);
return null;
}
简而言之,尽量避免在一种方法中混合使用异步等待和直接任务操作。
如果没有 async
关键字,您将从 AAA
返回 TaskCompletionSource
的任务,因此您等待它完成(这将在延迟完成后发生)。
但是,当您添加 async
关键字时,该方法返回的任务是同步完成的状态机任务。该任务包含(因此)TaskCompletionSource
的任务,但这不是您正在等待的任务。
如果您希望该方法等待 TaskCompletionSource
的任务,您可以等待 Task<Task>
的内部任务:
await ((Task) await AAA(3000));
或者等待 TaskCompletionSource
而不是返回它:
async Task AAA(int a)
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Task.Delay(a).ContinueWith(b => tcs.SetResult(null));
await tcs.Task;
}
或者更好,只是等待 Task.Delay
本身:
async Task<object> AAA(int a)
{
await Task.Delay(a);
return null;
}
如 Serg 所述,请查看 Visual Studio 中的示例:
static async Task<int> AAA(int a) // <--- No `async`
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
Task.Delay(a).ContinueWith(b =>
{
tcs.SetResult(1);
});
return tcs.Task;
}
你会得到这样的错误:
由于这是一个异步方法,return 表达式的类型必须是 'int' 而不是 'Task',因为您的方法将运行 同步。这就是为什么需要 return int
,而不是 Task
.