异步方法调用阻塞主线程

问题描述 投票:0回答:1

我有一个像这样的

async
方法:

public async Task SpecifyAsync()
{
    CancellationTokenSource source = new();
    Task<long> checkTask = BeginCheckingAsync(source.Token);
    SendMessage();
    await сheckTask;
}

异步方法在第二行调用。据我了解,这不应该阻止主执行线程。但是,在

checkTask
完成之前,无法访问第三行。请你描述一下我,我做错了什么吗?

UPD。

BeginCheckingAsync
代码是这样的:

private async Task<long> BeginCheckingAsync(CancellationToken cancellationToken)
{
    while (true)
    {
        var messages = _apiClient.GetNewMessages();

        foreach (var message in messages)
            if (ValidateMessage(message))
                return await Task.FromResult(Parse(message));

        cancellationToken.ThrowIfCancellationRequested();
    }
}
c# .net asynchronous async-await
1个回答
0
投票

您的方法有两个问题:

  1. 它不是真正的异步(因此在完成之前它不会返回给调用者)。等待完成的任务(即
    await Task.FromResult
    )不是异步操作,因此不会导致控制权传递给调用者。
  2. 即使等待完成的任务是一个异步操作,
    await
    中第一个
    BeginCheckingBalanceAsync
    之前的所有内容都将同步执行,即,如果
    _apiClient.GetNewMessages
    是一个长时间运行的操作或
    ValidateMessage
    将返回
    false
    对于某些迭代,等待第一个“真正异步”调用之前的所有内容都将同步执行

根据实际实现,您可以在方法的适当部分使用

Task.Run
。例如:

private async Task<long> BeginCheckingBalanceAsync(CancellationToken cancellationToken)
{
    while (true)
    {
        var messages = await Task.Run(_apiClient.GetNewMessages());

        foreach (var message in messages)
            if (ValidateMessage(message))
                return await Task.FromResult(Parse(message));

        cancellationToken.ThrowIfCancellationRequested();
    }
}

但是根据我应该为同步方法公开异步包装器吗?:

的答案

我对这个问题的简短回答是“不”。

在呼叫方使用

Task.Run

© www.soinside.com 2019 - 2024. All rights reserved.