Skip to content

Instantly share code, notes, and snippets.

@controlflow
Last active December 22, 2015 04:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save controlflow/6418329 to your computer and use it in GitHub Desktop.
Save controlflow/6418329 to your computer and use it in GitHub Desktop.
WCF Data Services Task-based async query API-extension
using System;
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Blah
{
public static class DataServiceContextExtensions
{
[NotNull]
public static IEnumerable<Task<List<T>>> QueryAsyncPaged<T>(
[NotNull] this IQueryable<T> query,
[NotNull] DataServiceContext context, CancellationToken cancellationToken)
{
var registration = new CancellationTokenRegistration();
var dataServiceQuery = (DataServiceQuery<T>)query;
DataServiceQueryContinuation<T> queryContinuation = null;
do
{
var completionSource = new TaskCompletionSource<List<T>>();
try
{
AsyncCallback callback = result =>
{
// ReSharper disable once AccessToModifiedClosure
// ReSharper disable once AccessToDisposedClosure
registration.Dispose();
try
{
var results = context.EndExecute<T>(result);
var list = new List<T>(results ?? Enumerable.Empty<T>());
var response = results as QueryOperationResponse<T>;
if (response != null)
queryContinuation = response.GetContinuation();
completionSource.TrySetResult(list);
}
catch (Exception exception)
{
// DataServices EndExecute() throws IOE if query is cancelled
if (exception is InvalidOperationException &&
cancellationToken.IsCancellationRequested)
completionSource.TrySetCanceled();
else
completionSource.TrySetException(exception);
}
};
var asyncResult = (queryContinuation == null)
? context.BeginExecute<T>(dataServiceQuery.RequestUri, callback, null)
: context.BeginExecute(queryContinuation, callback, null);
if (cancellationToken != CancellationToken.None)
{
registration = cancellationToken.Register(() =>
{
try { context.CancelRequest(asyncResult); } catch { }
});
}
}
catch (Exception exception)
{
completionSource.TrySetException(exception);
registration.Dispose();
}
yield return completionSource.Task;
try
{
completionSource.Task.Wait(cancellationToken);
}
catch (OperationCanceledException)
{
completionSource.TrySetCanceled();
}
catch (Exception exception)
{
completionSource.TrySetException(exception);
}
}
while (queryContinuation != null);
}
}
}
@yevhen
Copy link

yevhen commented Sep 3, 2013

Шо за мрачилова?

@controlflow
Copy link
Author

Никогда не видел Task-оберток над старыми Begin/End-апишками с маниакальным exception handling'ом и протаскиванием CancellationToken? Счастливый человек :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment