为什么如果我使用new Task(action) -> .Start()来创建任务,而不是使用Task.Run(),调用任何异步方法时任务会停止执行?

17 浏览
0 Comments

为什么如果我使用new Task(action) -> .Start()来创建任务,而不是使用Task.Run(),调用任何异步方法时任务会停止执行?

我发现如果按照以下方式构建一个新的任务:\nvar task = new Task(async action); task.Start();,\n任何对任何异步方法的调用(await Task.Delay()await new WebClient().DownloadStringAsync()等)都会忽略await运算符,并立即返回到主线程。\n如果我使用Task.Run(async action)方式运行相同的操作,那么相同的代码将按预期工作。\n示例代码:\n

class Program
{
    static async Task Main()
    {
        // 第一种方式 - 它可以正常工作
        var goodTask = Task.Run(async () => await ProblemMethod("goodTask"));
        await goodTask;
        Console.WriteLine($"{DateTime.Now:HH:mm:ss} :: {nameof(goodTask)}已完成。");
        // 第二种方式 - 在调用GetRequestStreamAsync的行上没有任何异常,但是失败了
        var poorTask = new Task(async () => await ProblemMethod("poorTask"));
        poorTask.Start();
        await poorTask;
        Console.WriteLine($"{DateTime.Now:HH:mm:ss} :: {nameof(poorTask)}已完成。");
        Console.ReadLine();
    }
    static async Task ProblemMethod(string taskName)
    {
        Console.WriteLine($"{taskName} :: {DateTime.Now:HH:mm:ss} :: 这是第一行。");
        await Task.Delay(2000);
        Console.WriteLine($"{taskName} :: {DateTime.Now:HH:mm:ss} :: 这是最后一行。");
    }
}

\n控制台输出:\ngoodTask :: 18:52:50 :: 这是第一行。\ngoodTask :: 18:52:52 :: 这是最后一行。\n18:52:52 :: goodTask已完成。\npoorTask :: 18:52:52 :: 这是第一行。\n18:52:52 :: poorTask已完成。\npoorTask :: 18:52:54 :: 这是最后一行。\n\n为什么会有这种奇怪的行为?是的,我知道首选和推荐的方式是立即运行任务,通过Task.Run或Task.Factory.StartNew,但如果我不想立即运行我的任务,我该怎么办?

0
0 Comments

这个问题的出现的原因是,当使用`new Task(action).Start()`创建一个任务时,该任务的构造函数接受的是一个`Action`委托,而不是一个`Func`委托。因此,异步委托实际上并没有被正确地处理。

解决方法是改用`Task.Run()`方法来创建任务。`Task.Run()`方法接受一个`Func`委托作为参数,可以正确地处理异步委托。

在实际应用中,如果需要执行异步方法,并且希望任务能够正确地执行,可以使用以下代码:

Task.Run(async () =>
{
    await YourAsyncMethod();
});

使用`Task.Run()`方法创建任务并在其中调用异步方法,可以确保任务能够正确地执行异步操作。这样可以避免使用`new Task(action).Start()`时可能出现的问题。

,使用`new Task(action).Start()`创建任务时,由于异步委托没有被正确处理,任务可能会停止执行。为了解决这个问题,可以使用`Task.Run()`方法来创建任务,并在其中调用异步方法。这样可以确保任务能够正确地执行异步操作。

0