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

docs から次のコメントを見つけました。

OperationContextScope ブロック内で非同期の「待機」パターンを使用しないでください。継続が発生すると、別のスレッドで実行される可能性があり、OperationContextScope はスレッド固有です。非同期呼び出しで「await」を呼び出す必要がある場合は、OperationContextScope ブロックの外で使用します。

したがって、明らかにサービスを間違って呼び出しているようです。しかし、正しい方法は何ですか?

4

3 に答える 3

19

Microsoftのドキュメントによると:

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;
于 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 に答える