c# - C# 中的异步方法不是异步的?

标签 c# asynchronous task-parallel-library async-await

创建了以下控制台应用程序后,我有点困惑为什么它似乎是同步运行而不是异步运行:

class Program
{
    static void Main(string[] args)
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        var total = CreateMultipleTasks();
        stopwatch.Stop();

        Console.WriteLine("Total jobs done: {0} ms", total.Result);
        Console.WriteLine("Jobs done in: {0} ms", stopwatch.ElapsedMilliseconds);
    }

    static async Task<int> CreateMultipleTasks()
    {
        var task1 = WaitForMeAsync(5000);
        var task2 = WaitForMeAsync(3000);
        var task3 = WaitForMeAsync(4000);

        var val1 = await task1;
        var val2 = await task2;
        var val3 = await task3;

        return val1 + val2 + val3;

    }

    static Task<int> WaitForMeAsync(int ms)
    {
        Thread.Sleep(ms);
        return Task.FromResult(ms);
    }
}

运行应用程序时,输出为:

Total jobs done: 12000 ms
Jobs done in: 12003 ms

我本以为会是这样的:

Total jobs done: 12000 ms
Jobs done in: 5003 ms

这是因为当我使用 Thread.Sleep 方法时它停止了整个应用程序的进一步执行吗?还是我在这里遗漏了一些重要的东西?

最佳答案

即使您像其他答案所建议的那样转换为使用 Task.RunTask.Delay您也应该避免使用阻塞 Task.WaitAll async 方法 中的任何位置,尽可能多。混合异步和同步代码通常不是一个好主意,它会增加冗余阻塞线程的数量并促进死锁。

相反,使用 await Task.WhenAll 并将阻塞等待移动到顶层(即,在这种情况下为 Main 方法):

class Program
{
    static void Main(string[] args)
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        var total = CreateMultipleTasks();

        total.Wait();

        stopwatch.Stop();

        Console.WriteLine("Total jobs done: {0} ms", total.Result);
        Console.WriteLine("Jobs done in: {0} ms", stopwatch.ElapsedMilliseconds);
    }

    static async Task<int> CreateMultipleTasks()
    {
        var task1 = Task.Run(() => WaitForMeAsync(5000));
        var task2 = Task.Run(() => WaitForMeAsync(3000));
        var task3 = Task.Run(() => WaitForMeAsync(4000));

        await Task.WhenAll(new Task[] { task1, task2, task3 });

        return task1.Result + task2.Result + task3.Result;
    }

    static int WaitForMeAsync(int ms)
    {
        // assume Thread.Sleep is a placeholder for a CPU-bound work item
        Thread.Sleep(ms);
        return ms;
    }
}

在旁注中,查看 Stephen Toub 的 "Should I expose asynchronous wrappers for synchronous methods?""Should I expose asynchronous wrappers for synchronous methods?"

关于c# - C# 中的异步方法不是异步的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23603526/

相关文章:

c# - 相继执行多个请求时出现 MySql 异常

c# - 设置超时异步 Web 服务调用?

task-parallel-library - 如何在 LinqPad 中转储最新列表?

c# - TPL 数据流本地存储或类似的东西

c# - 模态进度表显示 IProgress 并支持取消 WinForms 的异步任务

c# - 下拉没有 id 也没有名字

c# - C#COM端口通讯问题

c# - System.Environment.TickCount 的 WinRT 替换

c# - ConfigureAwait(true) 是否总是返回到原始线程,即使被调用方方法在内部执行 ConfigureAwait(false)?

c# - 如何安全地混契约(Contract)步和异步代码?