异步返回对象列表

时间:2014-09-26 17:59:12

标签: c# linq asynchronous

我正在尝试遍历结果集,运行查询以检索数据,然后将该数据添加到列表并返回它。

问题是,我试图异步执行此操作,我收到错误:

  

'System.Collections.Generic.List'   不包含'ToListAsync'的定义和最佳扩展名   方法过载   'System.Data.Entity.QueryableExtensions.ToListAsync(System.Linq.IQueryable)'   有一些无效的论点

以下是该方法的代码:

public async Task<List<IHFData>> GetHFServiceData(string wtTransfereeId)
{
    var hfDataList = new List<HFData>();

    Parallel.ForEach(aauthorizationList, item =>
    {
        // code to retrieve data from database (truncated)
        HFData hfData = Db.hfAuthorizations.AsNoTracking()....SingleOrDefault();

        hfDataList.Add(hfData);
    }

    return await hfDataList.ToListAsync(); // errors on this line
}

如何异步构建和返回我的列表?

2 个答案:

答案 0 :(得分:5)

正如错误消息告诉您的那样,没有List方法可以异步创建列表。无论如何,你已经有了一个清单。

从多个线程添加项目到列表也是不安全的,正如您从并行foreach循环中所做的那样。

您也不应该首先对集合中的每个项目执行数据库查询。相反,您应该执行单个数据库查询,该查询根据您拥有的列表中的信息获取所需的所有项目。该查询应以对ToListAsync的调用结束。

此处也不需要async方法,您只需直接返回ToListAsync的结果。

答案 1 :(得分:3)

您的代码存在一些巨大问题。

首先,您在hfDataList.Add内部调用Parallel.ForEachList<T>不是线程安全的,您无法在不锁定的情况下调用Add。

第二,因为错误告诉您ToListAsync只能在具有接口IQueryable<T>的类型上调用,所以您在List<T>上调用它而不实现该接口。

执行查询的正确方法是

public Task<List<IHFData>> GetHFServiceData(string wtTransfereeId)
{
    return Db.hfAuthorizations.AsNoTracking()....ToListAsync()
}

你需要修改你所取出的....中的任何内容,以便一次返回一组结果而不是一个结果。

此外await是不必要的,它是您函数中的最后一行,您只需返回Task directly并简化生成的代码并减少开销。


如果您无法将其更改为设置查询(并且您应该尝试,它将极大地提高您的性能)那么以旧方式执行此操作的方法是删除并行(实体框架可以&# 39; t处理它或者只做一个正常的foreach循环,然后等待异步版本的SingleOrDefault

public async Task<List<IHFData>> GetHFServiceData(string wtTransfereeId)
{
    var hfDataList = new List<HFData>();

    foreach(var item in aauthorizationList)
    {
        // code to retrieve data from database (truncated)
        HFData hfData = await Db.hfAuthorizations.AsNoTracking()....SingleOrDefaultAsync(); //This method is now async.

        hfDataList.Add(hfData);
    }

    //just return the list when you are done.
    return hfDataList; 
}