我有一个像这样的
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();
}
}
您的方法有两个问题:
await Task.FromResult
)不是异步操作,因此不会导致控制权传递给调用者。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
。