Async WCF-клиент вызывает пользовательские заголовки: этот OperationContextScope отключается

Я вызываю службу WCF из приложения WinRT. Служба требует, чтобы некоторые заголовки были настроены для аутентификации. Проблема заключается в том, что если я выполняю несколько вызовов службы одновременно, я получаю следующее исключение:

Этот OperationContextScope отключается.

Текущий код выглядит следующим образом:

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);
    }
}

Я нашел следующий комментарий из документов:

Не используйте асинхронный шаблон "ожидание" в блоке OperationContextScope. Когда это происходит, он может работать в другом потоке, а OperationContextScope - конкретный поток. Если вам нужно вызвать "ожидание" для асинхронного вызова, используйте его вне блока OperationContextScope.

Так что, похоже, я неправильно звоню в службу. Но каков правильный путь?

Ответ 1

Все, кажется, хорошо работает со следующим кодом:

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);
    }
}

Ответ 2

Это известная проблема, и для тех, кто застрял в этом, вы можете просто запустить ваш вызов синхронно. Используйте GetAwaiter(). GetResult(); вместо того, чтобы не планировать задачу вообще, она просто блокирует вызывающий поток, пока задача не будет завершена.

public Result CallServer()
{
    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).GetAwaiter().GetResult();
    }
}