如果我使用 new Task(action) -> .Start() 而不是 Task.Run() 创建它,为什么 Task 在调用任何异步方法时停止执行?
Why Task stops executing on call any async method if I create it with new Task(action) -> .Start() instead of Task.Run()?
我发现如果使用以下方式构造一个新任务:
var task = new Task(async action); task.Start();
,
任何异步方法(await Task.Delay()
、await new WebClient().DownloadStringAsync()
等)的任意调用都可能会忽略 await
运算符并立即返回到主线程。
如果我 运行 使用 Task.Run(async action)
方式执行相同的操作,那么相同的代码将按预期工作。
示例代码:
class Program
{
static async Task Main()
{
// way1 - it's working
var goodTask = Task.Run(async () => await ProblemMethod("goodTask"));
await goodTask;
Console.WriteLine($"{DateTime.Now:HH:mm:ss} :: {nameof(goodTask)} is finished.");
// way2 - it fails without any exceptions on line with GetRequestStreamAsync
var poorTask = new Task(async () => await ProblemMethod("poorTask"));
poorTask.Start();
await poorTask;
Console.WriteLine($"{DateTime.Now:HH:mm:ss} :: {nameof(poorTask)} is finished.");
Console.ReadLine();
}
static async Task ProblemMethod(string taskName)
{
Console.WriteLine($"{taskName} :: {DateTime.Now:HH:mm:ss} :: It's a first line.");
await Task.Delay(2000);
Console.WriteLine($"{taskName} :: {DateTime.Now:HH:mm:ss} :: It's a last line.");
}
}
控制台输出:
goodTask :: 18:52:50 :: It's a first line.
goodTask :: 18:52:52 :: It's a last line.
18:52:52 :: goodTask is finished.
poorTask :: 18:52:52 :: It's a first line.
18:52:52 :: poorTask is finished.
poorTask :: 18:52:54 :: It's a last line.
为什么行为如此奇怪?而且,是的,我知道首选和推荐的方法是通过 Task.Run 或 Task.Factory.StartNew 立即 运行 任务,但是如果我不想 [=30] 我该怎么办=] 我的任务立即执行?
讨论了答案here。本质上,Task
构造采用 Action<>
而不是 Func<>
,因此异步委托并没有真正被如此对待。
我发现如果使用以下方式构造一个新任务:
var task = new Task(async action); task.Start();
,
任何异步方法(await Task.Delay()
、await new WebClient().DownloadStringAsync()
等)的任意调用都可能会忽略 await
运算符并立即返回到主线程。
如果我 运行 使用 Task.Run(async action)
方式执行相同的操作,那么相同的代码将按预期工作。
示例代码:
class Program
{
static async Task Main()
{
// way1 - it's working
var goodTask = Task.Run(async () => await ProblemMethod("goodTask"));
await goodTask;
Console.WriteLine($"{DateTime.Now:HH:mm:ss} :: {nameof(goodTask)} is finished.");
// way2 - it fails without any exceptions on line with GetRequestStreamAsync
var poorTask = new Task(async () => await ProblemMethod("poorTask"));
poorTask.Start();
await poorTask;
Console.WriteLine($"{DateTime.Now:HH:mm:ss} :: {nameof(poorTask)} is finished.");
Console.ReadLine();
}
static async Task ProblemMethod(string taskName)
{
Console.WriteLine($"{taskName} :: {DateTime.Now:HH:mm:ss} :: It's a first line.");
await Task.Delay(2000);
Console.WriteLine($"{taskName} :: {DateTime.Now:HH:mm:ss} :: It's a last line.");
}
}
控制台输出:
goodTask :: 18:52:50 :: It's a first line.
goodTask :: 18:52:52 :: It's a last line.
18:52:52 :: goodTask is finished.
poorTask :: 18:52:52 :: It's a first line.
18:52:52 :: poorTask is finished.
poorTask :: 18:52:54 :: It's a last line.
为什么行为如此奇怪?而且,是的,我知道首选和推荐的方法是通过 Task.Run 或 Task.Factory.StartNew 立即 运行 任务,但是如果我不想 [=30] 我该怎么办=] 我的任务立即执行?
讨论了答案here。本质上,Task
构造采用 Action<>
而不是 Func<>
,因此异步委托并没有真正被如此对待。