Asynchronous 有人能描述一下这个递归异步Azure存储调用中的逻辑是如何流动的吗?

Asynchronous 有人能描述一下这个递归异步Azure存储调用中的逻辑是如何流动的吗?,asynchronous,c#-3.0,azure,cloud,azure-storage,Asynchronous,C# 3.0,Azure,Cloud,Azure Storage,有人能帮我理解这段代码是如何执行的,结果在哪里,在什么时候我才能开始处理完整的结果 protected void QuerySongsExecuteSegmentedAsync(CloudTableClient cloudTableClient) { TableServiceContext tableServiceContext = cloudTableClient.GetDataServiceContext(); tableServiceContext.ResolveType = (u

有人能帮我理解这段代码是如何执行的,结果在哪里,在什么时候我才能开始处理完整的结果

protected void QuerySongsExecuteSegmentedAsync(CloudTableClient cloudTableClient)
{
  TableServiceContext tableServiceContext = cloudTableClient.GetDataServiceContext();
  tableServiceContext.ResolveType = (unused) => typeof(Song); 

  CloudTableQuery<Song> cloudTableQuery =
    (from entity in tableServiceContext.CreateQuery<Song>("Songs").Take(10)
    select entity ).AsTableServiceQuery<Song>();
  IAsyncResult iAsyncResult =
    cloudTableQuery.BeginExecuteSegmented(BeginExecuteSegmentedIsDone, cloudTableQuery);
} 

static void BeginExecuteSegmentedIsDone(IAsyncResult result)
{
  CloudTableQuery<Song> cloudTableQuery = result.AsyncState as CloudTableQuery<Song>;
  ResultSegment<Song> resultSegment = cloudTableQuery.EndExecuteSegmented(result); 

  List<Song> listSongs = resultSegment.Results.ToList<Song>(); 

  if (resultSegment.HasMoreResults)
  {
    IAsyncResult iAsyncResult =
      cloudTableQuery.BeginExecuteSegmented(
       resultSegment.ContinuationToken, BeginExecuteSegmentedIsDone, cloudTableQuery);
  }
}

针对Windows Azure表存储的查询可以返回带有延续令牌的部分结果,这意味着您需要使用延续令牌重新发出查询以获得下一批结果。通常,您将看到只使用.AsTableServiceQuery然后枚举的代码,这将导致在枚举期间透明地发生调用链


这段代码通过使用BeginExecuteSegmented检索每一批结果来显式地实现这一点。在列表listSongs=resultSegment.Results.ToList行的正下方,您应该能够使用这些歌曲。可能会有更多的结果,但这些结果应该是有效的和可用的。

针对Windows Azure表存储的查询可以返回带有延续令牌的部分结果,这意味着您需要使用延续令牌重新发出查询以获得下一批结果。通常,您将看到只使用.AsTableServiceQuery然后枚举的代码,这将导致在枚举期间透明地发生调用链


这段代码通过使用BeginExecuteSegmented检索每一批结果来显式地实现这一点。在列表listSongs=resultSegment.Results.ToList行的正下方,您应该能够使用这些歌曲。可能还会有更多,但这些结果应该是有效的和可用的。

如果您想使用TPL任务并行库异步执行,您可以使用这样的模式

    public static Task<IEnumerable<T>> ExecuteAsync<T>(DataServiceQuery<T> query, TableServiceContext tableContext)
    {
        List<T> values = null;

        var cloudQuery = query.AsTableServiceQuery();

        Func<ResultSegment<T>, Task<ResultSegment<T>>> getSegment = null;

        getSegment = new Func<ResultSegment<T>, Task<ResultSegment<T>>>((previous) =>
        {
            return ExecuteSegmentAsync(cloudQuery, previous).ContinueWith(exec =>
            {                    
                if (exec.IsFaulted || exec.IsCanceled)
                {
                    return exec;
                }
                else
                {
                    var segment = exec.Result;
                    if(segment.HasMoreResults)
                    {
                        if(values == null)
                        {
                            values = new List<T>();
                        }
                        values.AddRange(segment.Results);
                        return getSegment(segment);                        
                    }
                    else
                    {
                        return exec;
                    }
                }
            }).Unwrap();
        });

        return getSegment(null).ContinueWith(exec =>
        {
            exec.ThrowOnError("ExecuteAsync");
            var segment = exec.Result;

            if(values == null)
            {
                return segment.Results;
            }
            else
            {
                values.AddRange(segment.Results);
                return values;
            }
        });       
    }

    private static Task<ResultSegment<T>> ExecuteSegmentAsync<T>(CloudTableQuery<T> query, ResultSegment<T> previous)
    {
        var tcs = new TaskCompletionSource<ResultSegment<T>>();

        RetryPolicy.ExecuteAction(ac =>
        {
            // Invoke the begin method of the asynchronous call.
            if(previous != null)
            {
                query.BeginExecuteSegmented(previous.ContinuationToken, ac, null);                
            }
            else
            {
                query.BeginExecuteSegmented(ac, null);                
            }
        },
        ar =>
        {
            // Invoke the end method of the asynchronous call.
            return query.EndExecuteSegmented(ar);
        },
        values =>
        {
            tcs.SetResult(values);                
        },
        ex =>
        {
            // Async opetation failed after multiple retries
            tcs.SetException(ex);
        });

        return tcs.Task;
    }

如果您想使用TPL任务并行库异步执行,可以使用如下模式

    public static Task<IEnumerable<T>> ExecuteAsync<T>(DataServiceQuery<T> query, TableServiceContext tableContext)
    {
        List<T> values = null;

        var cloudQuery = query.AsTableServiceQuery();

        Func<ResultSegment<T>, Task<ResultSegment<T>>> getSegment = null;

        getSegment = new Func<ResultSegment<T>, Task<ResultSegment<T>>>((previous) =>
        {
            return ExecuteSegmentAsync(cloudQuery, previous).ContinueWith(exec =>
            {                    
                if (exec.IsFaulted || exec.IsCanceled)
                {
                    return exec;
                }
                else
                {
                    var segment = exec.Result;
                    if(segment.HasMoreResults)
                    {
                        if(values == null)
                        {
                            values = new List<T>();
                        }
                        values.AddRange(segment.Results);
                        return getSegment(segment);                        
                    }
                    else
                    {
                        return exec;
                    }
                }
            }).Unwrap();
        });

        return getSegment(null).ContinueWith(exec =>
        {
            exec.ThrowOnError("ExecuteAsync");
            var segment = exec.Result;

            if(values == null)
            {
                return segment.Results;
            }
            else
            {
                values.AddRange(segment.Results);
                return values;
            }
        });       
    }

    private static Task<ResultSegment<T>> ExecuteSegmentAsync<T>(CloudTableQuery<T> query, ResultSegment<T> previous)
    {
        var tcs = new TaskCompletionSource<ResultSegment<T>>();

        RetryPolicy.ExecuteAction(ac =>
        {
            // Invoke the begin method of the asynchronous call.
            if(previous != null)
            {
                query.BeginExecuteSegmented(previous.ContinuationToken, ac, null);                
            }
            else
            {
                query.BeginExecuteSegmented(ac, null);                
            }
        },
        ar =>
        {
            // Invoke the end method of the asynchronous call.
            return query.EndExecuteSegmented(ar);
        },
        values =>
        {
            tcs.SetResult(values);                
        },
        ex =>
        {
            // Async opetation failed after multiple retries
            tcs.SetException(ex);
        });

        return tcs.Task;
    }

如果我有一张有20000行的桌子,我想要所有的行,Take10似乎有点低。我应该把什么更现实的数字放在那里?每个查询的最大值是100?1000错误在System.Data.Client?中不再发出记录之前的最大值。。。或者其他价值?啊,我没有注意到Take10。你可以把Take10放在那里,然后你可以一次得到尽可能多的东西。最大值是1000,而不是100。我不知道你在说什么错误?如果我有一张20000行的桌子,我想要所有的行,Take10似乎有点低。我应该把什么更现实的数字放在那里?每个查询的最大值是100?1000错误在System.Data.Client?中不再发出记录之前的最大值。。。或者其他价值?啊,我没有注意到Take10。你可以把Take10放在那里,然后你可以一次得到尽可能多的东西。最大值是1000,而不是100。我不知道你在说什么虫子?