WCF with async await logic

I found this very interesting post to get a Task<T> from a WCF call.

I change it a little bit to fix a bug and to allow usage of async / await using AsyncCtpLibrary.

So I propose this implementation:

public static class TaskFactoryExtensions
{
    public static async Task<TResult> ToTask<TResult>(this IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod)
    {
        var taskCompletionSource = new TaskCompletionSource<TResult>();
        if (asyncResult.IsCompleted)
            taskCompletionSource.TrySetResult(asyncResult, endMethod);
        else
        {
            object lockObject = new object();
            bool proccessed = false;
            ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, (state, timeOut) =>
            {
                if (proccessed)
                    return;
                lock (lockObject)
                {
                    if (proccessed)
                        return;
                    proccessed = true;
                }
                taskCompletionSource.TrySetResult(asyncResult, endMethod);
            }, null, -1, true);
            if (asyncResult.IsCompleted)
            {
                lock (lockObject)
                {
                    if (!proccessed)
                    {
                        proccessed = true;
                        taskCompletionSource.TrySetResult(asyncResult, endMethod);
                    }
                }
            }
        }
        TResult value = await taskCompletionSource.Task;
        return value;
    }
 
    private static void TrySetResult<TResult>(this TaskCompletionSource<TResult> taskCompletionSource, IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod)
    {
        try
        {
            var result = endMethod(asyncResult);
            taskCompletionSource.TrySetResult(result);
        }
        catch (OperationCanceledException)
        {
            taskCompletionSource.TrySetCanceled();
        }
        catch (Exception e)
        {
            taskCompletionSource.TrySetException(e);
        }
    }
}

So now, I can use this code to call my WCF Service:

private async Task<List<Customer>> GetCustomers()
{
    var service = new MyService();
    return await service.BeginGetCustomers(null, null).ToTask(ar => service.EndGetCustomers(ar));

}

Enjoy! :)

 

Update : With AsyncCtpLibrary, we could just do it:

return await Task.Factory.FromAsync(service.BeginGetCustomers(null, null), ar => service.EndGetCustomers(ar));

This entry was posted in 10369, 11417, 16710, 7671. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>