31

我正在从 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);
    }
}

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

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

所以看来我显然错误地调用了该服务。但正确的方法是什么?

4

3 回答 3

19

根据微软文档

不要在 OperationContextScope 块中使用异步“等待”模式。当继续发生时,它可能在不同的线程上运行,并且 OperationContextScope 是特定于线程的。如果您需要为异步调用调用“等待”,请在 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;
于 2020-03-30T07:19:51.593 回答
10

这是一个已知的“问题”,对于任何遇到此问题的人,您都可以简单地同步运行您的呼叫。使用 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();
    }
}
于 2018-05-25T11:02:08.500 回答
7

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

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);
    }
}
于 2012-11-02T07:43:45.603 回答