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。我不知道你在说什么虫子?