Асинхронные вызовы клиента 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);
    }
}

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

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

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

2 ответов


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

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

Это известная "проблема" и для тех, кто застрял с этим, вы можете просто запустить ваш звонок синхронно. Используйте 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();
    }
}