如何将Table.ExecuteQuerySegmentedAsync()与Azure表存储一起使用

Hal*_*nac 8 c# asynchronous azure azure-table-storage async-await

使用Azure存储客户端库2.1,我正在进行表存储异步查询.我创建了这段代码:

public async Task<List<TAzureTableEntity>> GetByPartitionKey(string partitionKey)
{
    var theQuery = _table.CreateQuery<TAzureTableEntity>()
                         .Where(tEnt => tEnt.PartitionKey == partitionKey);
    TableQuerySegment<TAzureTableEntity> querySegment = null;
    var returnList = new List<TAzureTableEntity>();
    while(querySegment == null || querySegment.ContinuationToken != null)
    {
        querySegment = await theQuery.AsTableQuery()
                                     .ExecuteSegmentedAsync(querySegment != null ?
                                         querySegment.ContinuationToken : null);
        returnList.AddRange(querySegment);
    }
    return returnList;
}
Run Code Online (Sandbox Code Playgroud)

假设有大量数据返回,因此会有很多往返表存储的往返.我遇到的问题是我们正在等待一组数据,将其添加到内存列表中,等待更多数据,将其添加到同一列表中,等待更多数据,将其添加到列表中......等等等等.为什么不围绕常规TableQuery包装Task.Factory.StartNew()?像这样:

public async Task<List<TAzureTableEntity>> GetByPartitionKey(string partitionKey)
{
    var returnList = await Task.Factory.StartNew(() =>
                                                 table.CreateQuery<TAzureTableEntity>()
                                                .Where(ent => ent.PartitionKey == partitionKey)
                                                .ToList());
    return returnList;
}
Run Code Online (Sandbox Code Playgroud)

这样做似乎我们不会来回反复播放SynchronizationContext.或者它真的重要吗?

编辑以改写问题

上面提到的两种情况有什么区别?

svi*_*ick 6

两者之间的区别在于您的第二个版本将ThreadPool在执行查询的整个过程中阻塞一个线程.这在GUI应用程序中是可以接受的(你想要的只是在UI线程以外的地方执行代码),但它会否定async服务器应用程序中的任何可伸缩性优势.

此外,如果您不希望第一个版本返回到每个往返的UI上下文(这是一个合理的要求),那么ConfigureAwait(false)无论何时使用都使用await:

querySegment = await theQuery.AsTableQuery()
                             .ExecuteSegmentedAsync(…)
                             .ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

这样,第一个之后的所有迭代将(很可能)在ThreadPool线程上而不是在UI上下文上执行.

顺便说一句,在你的第二个版本中,你根本不需要await,你可以直接返回Task:

public Task<List<TAzureTableEntity>> GetByPartitionKey(string partitionKey)
{
    return Task.Run(() => table.CreateQuery<TAzureTableEntity>()
                               .Where(ent => ent.PartitionKey == partitionKey)
                               .ToList());
}
Run Code Online (Sandbox Code Playgroud)

  • 疑难杂症.没有意识到在等待`QuerySegment`返回数据时它没有占用`ThreadPool`线程.具有讽刺意味的是,在深入挖掘您之前的评论时,我发现了您对此主题的另一个好答案.:-)这是链接,以防其他人发现它像我一样有用.http://stackoverflow.com/a/14898584/350312 (2认同)