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>