使用自定义标头的异步WCF客户端调用:此OperationContextScope正在按顺序处理

时间:2012-11-02 05:45:36

标签: c# wcf asynchronous wcf-client

我正在从WinRT应用程序调用WCF服务。该服务要求为身份验证设置一些标头。问题是如果我同时多次调用 ,我会收到以下异常:

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

我找到了以下评论from the docs

  

不要在OperationContextScope块中使用异步“await”模式。当继续发生时,它可以在不同的线程上运行,而OperationContextScope是特定于线程的。如果需要为异步调用调用“await”,请在OperationContextScope块之外使用它。

所以我似乎错误地调用了该服务。但是正确的方法是什么?

3 个答案:

答案 0 :(得分:12)

根据Microsoft documentation

请勿在OperationContextScope块内使用异步“等待”模式。发生延续时,它可以在其他线程上运行,并且OperationContextScope是特定于线程的。如果您需要为异步调用调用“ await”,请在OperationContextScope块之外使用它。

所以最简单的正确解决方案是:

Task<ResponseType> task;
using (new OperationContextScope(client.InnerChannel))
{
    OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = GetHeader();

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

    task = client.GetDataFromServerAsync(request);
}

var result = await task;

答案 1 :(得分:5)

使用以下代码似乎一切都很好:

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 :(得分:5)

这是一个已知的问题&#34;对于任何坚持这个的人,你可以简单地同步运行你的电话。使用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();
    }
}