WCF using TAP without worrying about timeouts I really like using the new TAP pattern in .Net 4.5. and I am updating some of my older projects to use it.

One of my old patterns was to use EAP with WCF so I could have functions that could take longer than 60 seconds (the default timeout for WCF) to complete without doing custom setup on the client side App.Conifg.

Here is a simple example of what I would do.

[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IService1
{
    [OperationContract(IsOneWay = true)]
    void Test(int arg);
}

[ServiceContract]
interface ICallback
{
    [OperationContract(IsOneWay=true)]
    void Callback(int arg);
}

public class Service1 : IService1
{
    public void Test(int arg)
    {
        var callback = OperationContext.Current.GetCallbackChannel&lt;ICallback&gt;();
        Thread.Sleep(61000); //Sleep for 61 sec.
        callback.Callback(arg + 1);
    }
}


Now I want to put a wrapper around my EAP pattern and turn it in to a TAP pattern (as an aside, just returning a TAP pattern like public Task&lt;int&gt; Test(int arg) will still have the 60 second time limit but it does work)

Here is the solution I came up with, this code would be run on the client.

static class ProxyClient
{
    private delegate void CallbackDelegate(int arg);

    private class CallbackClass : IService1Callback
    {
        public event CallbackDelegate CallbackEvent;

        void IService1Callback.Callback(int arg)
        {
            var tmp = CallbackEvent;
            if (tmp != null)
                tmp(arg);
        }
    }

    public static async Task&lt;int&gt; Test(int arg)
    {
        var callback = new CallbackClass();
        var client = new Service1Client(new InstanceContext(callback));
        TaskCompletionSource&lt;int&gt; tcs = new TaskCompletionSource&lt;int&gt;();

        //start listening for the completion event
        callback.CallbackEvent += (resultArg) =&gt; tcs.TrySetResult(resultArg);

        client.Test(arg);

        //wait for the result
        var result = await tcs.Task;

        //close the connection
        client.Close();

        return result;
    }
}


The main concern I had was receiving the completion callback for another invocation if a connection was used more than once. So I create and breakdown the connection from inside the function entirely.

I would love to hear input if this is a good idea, or is there a better way to accomplish long running tasks in WCF without having to modify timeout values client-side at the time of proxy creation.
Design Trigger

I don't understand why you implement a duplex wcf operation to emulate a simplex operation, just to avoid configuring the timeout. Let's assume you have a really good reason why you don't want to change the default timeouts, then your solution can still time out on being idle (after 10 minutes), because you changed from timing out on SendTimeout to ReceiveTimeout. 

As explained here the following timeouts have an impact on your code:


SendTimeout:
maximum threshold to expire an ongoing simplex operation. -> The timeout you don't like to configure (default: 1 minute)
ReceiveTimeout: 
maximum idle time on a session. -> The timeout between the one-way message and the callback fired back. (default: 10 minutes)




Review


Your concern about using a single instance for multiple calls is valid. Using a single instance with a single callback is the simplest solution. Otherwise, you would need to implement a matching system with correlation ids in the request and callback contracts.
The lifetime management is not robust enough. Use a try-finally block to close the connection. Also, distinguish between Abort (when connection is Faulted) and Close (graceful disconnect) (Close Connection).


//wait for the result
var result = await tcs.Task;  // &lt;- if this throws an exception

//close the connection
client.Close();       // &lt;- this won't be called