C# 在异步方法中处理异步调用返回的结果

C# 在异步方法中处理异步调用返回的结果,c#,async-await,C#,Async Await,假设这是一个执行DB查询并返回结果的方法,如果为null,则结果将替换为默认值 假设这个DB查询是一个长期运行的进程,所以我将使用async/await在单独的线程中执行这个进程。假设dbContext.GetSomeResultAsync方法可用 如何在异步方法中转换此方法,以便我可以编写类似的内容 var resultTask = GetAsync(); var otherResultTask = GetSomethingElseAsync(); Task.WaitAll(resultTa

假设这是一个执行DB查询并返回结果的方法,如果为null,则结果将替换为默认值

假设这个DB查询是一个长期运行的进程,所以我将使用async/await在单独的线程中执行这个进程。假设dbContext.GetSomeResultAsync方法可用

如何在异步方法中转换此方法,以便我可以编写类似的内容

var resultTask = GetAsync();
var otherResultTask = GetSomethingElseAsync();

Task.WaitAll(resultTask, otherResultTask);

var myResult = resultTask.Result;
var myOtherResult = otherResultTask.Result;
我试过这个方法

public async Task<ResultObj> GetAsync()
{
    var result = await dbContext.GetSomeResultAsync();

    return result ?? ResultObj.NullValue;
}
这也会导致死锁。这一次我甚至不知道为什么

编辑:可能的解决方案 最后,读完之后,我找到了解决问题的办法

我的通用查询包装器方法如下所示

public async Task<ResultObj> GetAsync()
{
    var result = await dbContext.GetSomeResultAsync();

    return result ?? ResultObj.NullValue;
}
在调用方法时,我使用这种模式

public async Task<CollectedResults> CollectAsync()
{
    var resultTask = GetAsync();
    var otherResultTask = GetSomethingElseAsync();

    //here both queries are being executed.
    //...in the while, optionally, here some other synchronous actions

    //then, await results
    var result = await resultTask;
    var otherResult = await otherResultTask;

    //here process collected results and return

    return new CollectedResults(...);
}
值得一提的是,封装在域类中的上述代码由控制器操作调用。为了让它工作,我必须使方法一直保持异步,直到控制器动作,现在显示如下

public async Task<CollectedResults> Get()
{
    return await resultsCollector.CollectAsync();
}
这样,死锁不再发生,执行时间相对于同步版本有了很大的提高


我不知道这是否是执行并行查询的标准方式。但它是有效的,我看不出代码中有什么特别的缺陷。

首先,关于:

因此,我将使用async/await在单独的线程中执行此过程

当我们使用async和Wait时

第二:

为什么我可以在预期任务时返回ResultObj

Task as return type of method告诉我们它返回一个类型为TResult的任务,但是我们需要从中返回类型为TResult的对象,这样就可以等待该方法,当使用Task as reutrn type时,我们应该使用async并等待执行该工作

最后:

这段代码会导致死锁

您正在使用带有方法签名的async关键字,并等待从该方法中执行下一个异步方法调用。显然,如果您使用的GetSomeResultAsync方法确实是一个异步方法并且得到了正确的实现,那么您发布的第一个示例中的代码就不应该处于死锁状态

我建议在开始讨论async Wait之前,多研究一下它,下面是一篇很好的文章:


由于异步/等待,它可以编译。这是关键字的一个特征。如果你返回一个任务,你会得到一个错误。您能告诉我为什么这会导致死锁吗?另外,async/await并不意味着另一个线程。这意味着,当您等待Db的结果时,而不是阻塞线程,您可以让线程执行其他操作,并在结果可用时返回。谢谢。实际上,我可以返回一个没有错误的任务。死锁发生的原因是这样的:谢谢你的有趣链接。我的异步方法当然实现得很好,因为它属于一个公共库。到目前为止,我的问题没有解决办法。如果我直接返回任务,而不在异步方法中检查null,然后在调用后每次在外部检查,则没有问题。
public async Task<CollectedResults> CollectAsync()
{
    var resultTask = GetAsync();
    var otherResultTask = GetSomethingElseAsync();

    //here both queries are being executed.
    //...in the while, optionally, here some other synchronous actions

    //then, await results
    var result = await resultTask;
    var otherResult = await otherResultTask;

    //here process collected results and return

    return new CollectedResults(...);
}
public async Task<CollectedResults> Get()
{
    return await resultsCollector.CollectAsync();
}