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

Mik*_*nen 20 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

从文档中找到了以下评论:

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

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

zol*_*y13 17

根据微软文档

不要在 OperationContextScope 块中使用异步“await”模式。当延续发生时,它可能在不同的线程上运行,而 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;
Run Code Online (Sandbox Code Playgroud)

  • 这似乎按预期工作。 (2认同)
  • 你救了我的命。 (2认同)

Dan*_*jel 7

这是一个已知的“问题”,对于任何对此困扰不已的人,您都可以简单地同步运行您的呼叫。使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Mik*_*nen 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这可能会奏效,但它会巧合.因为您没有等待GetDataFromServerAsync调用,所以不会发生线程切换.操作的上下文范围已在呼叫实际完成之前处理.它工作的原因可能是因为在内部调用等待内部之前添加了传出标头. (5认同)
  • 您可以等待任务GetDataFromServerAsync在using块结束后立即返回(将任务分配给变量). (2认同)