C# 如何度量等待异步操作的性能?

C# 如何度量等待异步操作的性能?,c#,task-parallel-library,async-await,performance-testing,c#-5.0,C#,Task Parallel Library,Async Await,Performance Testing,C# 5.0,我有一个Windows服务,可以读取多个MessageQueue实例。这些消息队列都运行自己的任务来读取消息。通常,在读取消息之后,I/O数据库的工作就完成了。我发现一些文章声称在I/O操作中使用异步是个好主意,因为它可以释放线程。我试图模拟在控制台应用程序中使用异步I/O操作的性能提升 控制台应用程序 在我的测试环境中,我有10个队列GetQueues()返回10个不同的MessageQueue实例 static void Main(string[] args) { var isAsy

我有一个Windows服务,可以读取多个
MessageQueue
实例。这些消息队列都运行自己的
任务
来读取消息。通常,在读取消息之后,I/O数据库的工作就完成了。我发现一些文章声称在I/O操作中使用异步是个好主意,因为它可以释放线程。我试图模拟在控制台应用程序中使用异步I/O操作的性能提升

控制台应用程序 在我的测试环境中,我有10个队列
GetQueues()
返回10个不同的
MessageQueue
实例

static void Main(string[] args)
{
    var isAsync = Console.ReadLine() == "Y";
    foreach (var queue in queueManager.GetQueues())
    {
        var temp = queue;
        Task.Run(() => ReceiveMessagesForQueue(temp, isAsync));
    }

    while (true)
    {
        FillAllQueuesWithMessages();
        ResetAndStartStopWatch();
        while(!AllMessagesRead())
        {
            Thread.Sleep(10);
        }
        Console.WriteLine("All messages read in {0}ms", stopWatch.ElapsedMilliseconds);
    }
}

static async Task ReceiveMessagesForQueue(MessageQueue queue, bool isAsync)
{
    while (true)
    {
        var message = await Task.Factory.FromAsync<Message>(queue.BeginReceive(), queue.EndReceive);

        if (isAsync)
            await ProcessMessageAsync(message);
        else
            ProcessMessage(message);
    }
}
同步消息处理 等待
Task.Delay()
,因此不应释放当前
线程

static async Task ProcessMessageAsync(Message message)
{
    await Task.Delay(1000);
    BurnCpu();
}
static void ProcessMessage(Message message)
{
    Task.Delay(1000).Wait();
    BurnCpu();
}
最终,结果是相同的。我是不是遗漏了什么

编辑1 我正在使用秒表测量总时间。ElapsedMilliseconds
。我使用
FillAllQueuesWithMessages()
将10、100、10000或更多消息填充到所有队列中

编辑2
ReceiveMessagesForQueue()
现在返回
Task
而不是
void

编辑3(修复)
这个测试确实显示了我现在的性能改进。我不得不让
BurnCpu()
花更多的时间。当等待
Task.Delay()
时,
BurnCPU()
可以使用释放的线程进行处理。

使用
async wait
不会加快执行单个操作所需的时间,这只意味着您没有线程在等待执行任何操作

在您的情况下,
任务。延迟
将花费一秒钟,无论发生什么,但在这里:

Task.Delay(1000).Wait();
您有一个线程,在此处等待第二个线程结束:

await Task.Delay(1000);
你没有。您仍然在异步等待(因此,
wait
),但没有使用线程,这意味着更好的可伸缩性

async await
中,您可以获得性能提升,因为您的应用程序可以用更少的线程执行相同的操作,或者用相同的线程执行更多操作。要衡量这一点,您需要同时进行大量的
异步
操作。只有这样,您才会注意到
async
选项比同步选项更好地利用了
CPU
资源



有关释放线程的详细信息,请参见此处

在使用默认任务计划程序时,您仍然在线程池中以自己的线程运行每个任务。如果希望看到性能提升,则需要确保在同一线程上执行多个任务


另外,对于20个并行任务,您可能不会看到任何差异。尝试2000个任务。

我知道我正在释放线程。以下是我无法想象的:如果我有一个4核处理器运行10个并行进程从队列中读取消息,那么在使用wait on
Task.Delay()时不应该是线程切换吗?我想使用已发布的线程。如果我为10个进程中的1个释放一个线程,为什么其他进程中没有一个使用该线程?@annemartijn当你说进程时,你是指线程吗?要改进async Wait的使用,您需要同时让CPU和IO(或其他异步)工作(在您的应用程序中)。这样,当一个线程在IO上被“阻塞”时,它可以去做其他CPU工作,而不是无所事事地等待。@annemartijn你没有错。使用“无线程异步”允许您同时执行更多IO(或异步)调用,因为它不会耗尽资源,线程可以同时执行CPU工作。这就是可伸缩性的含义。@annemartijn事实并非如此。当一个线程被阻塞时(例如使用thread.Sleep),CPU会将其切断并进行上下文切换。此外,您有4个以上的线程,如果需要,线程池可以创建更多线程。是的。异步不会缩短异步操作。需要多长时间就多长时间。但它释放了线程,所以您可以启动更多异步操作或使用CPU时间。