Search code examples
c#wcfasynchronouswcf-client

Async WCF client calls with custom headers: This OperationContextScope is being disposed out of order


I'm calling a WCF service from a WinRT app. The service requires that some headers are set for the authentication. The problem is that if I do multiple calls to the service simultaneously, I get the following exception:

This OperationContextScope is being disposed out of order.

The current code looks like the following:

public async Task<Result> CallServerAsync()
{
    var address = new EndpointAddress(url);
    var client = new AdminServiceClient(endpointConfig, address);

    using (new OperationContextScope(client.InnerChannel))
    {
        OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = GetHeader();

        var request = new MyRequest(...); 
        {
            context = context,
        };

        var result = await client.GetDataFromServerAsync(request);
    }
}

I found the following comment from the docs:

Do not use the asynchronous “await” pattern within a OperationContextScope block. When the continuation occurs, it may run on a different thread and OperationContextScope is thread specific. If you need to call “await” for an async call, use it outside of the OperationContextScope block.

So it seems I'm clearly calling the service incorrectly. But what is the correct way?


Solution

  • Everything seems to work quite well with the following code:

    public async void TestMethod()
    {
        var result = await CallServerAsync();
    }
    
    public Task<Result> CallServerAsync()
    {
        var address = new EndpointAddress(url);
        var client = new AdminServiceClient(endpointConfig, address);
    
        using (new OperationContextScope(client.InnerChannel))
        {
            OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = GetHeader();
    
            var request = new MyRequest(...); 
            {
                context = context,
            };
    
            return client.GetDataFromServerAsync(request);
        }
    }