有人可以描述这个递归异步 Azure 存储调用中的逻辑流程吗?

发布于 2024-10-13 12:01:12 字数 1166 浏览 3 评论 0原文

有人可以帮助我理解这段代码是如何执行的,“结果”在哪里,以及我什么时候可以开始用完整的结果做事情。

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);
  }
}

Can someone help me understand how this code is executed, and where the "result" is, and at what point can I start doing stuff with the complete result.

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);
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅听莫相离 2024-10-20 12:01:12

针对 Windows Azure 表存储的查询可以返回带有继续标记的部分结果,这意味着您需要重新发出查询(带有继续标记)才能获取下一批结果。通常,您会看到仅使用 .AsTableServiceQuery() 然后进行枚举的代码,这将导致该调用链在枚举期间透明地发生。

此代码通过使用 BeginExecuteSegmented 来检索每批结果来显式执行此操作。就在 List行下方listSongs = resultSegment.Results.ToList(),您应该能够使用这些 Song。 (可能还会有更多结果,但这些结果应该是有效且可用的。)

Queries against Windows Azure table storage can return partial results with a continuation token, which means you need to reissue the query (with the continuation token) to get the next batch of results. Typically, you'll see code that just uses .AsTableServiceQuery() and then enumerates, which will cause that chain of calls to happen transparently during enumeration.

This code is doing it explicitly, by using BeginExecuteSegmented to retrieve each batch of results. Right below the line List<Song> listSongs = resultSegment.Results.ToList<Song>(), you should be able to consume those Songs. (More may be coming, but those results should be valid and usable.)

花落人断肠 2024-10-20 12:01:12

如果您想使用 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;
    }

If you want to use TPL (Task Parallel Library) to execute asynchronously you can use a pattern like this.

    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;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文