3

これと同様に、コールバック コントラクトを使用してクライアントに通知する WCF サービスがあります。

public interface IClientCallback
{
    [OperationContract(IsOneWay = true)]
    void NotifySomething();
}

そしてそれを呼び出すサービスコードはこれに似ています

void NotifySomething()
{
    try
    {
        this.callback.NotifySomething();
    }
    catch (Exception ex)
    {
        // Log the exception and eat it
    }
}

設計上、コールバック通知はオプションであることに注意してください。つまり、あると便利ですが、必須ではありません。そのため、それはマークされてOneWayおり、実装は例外を食べます。

いくつかの誤解により、ブロックされていない発砲と忘却のメソッドを持つにはそれで十分だと考えていました。しかし、もちろんそうではありませんでした。そのため、状況によってはしばらくブロックされ、スレッド同期ブロック内から呼び出されるため、問題が発生しています。そこで、以下のように定義を変更して非同期にすることにしました

public interface IClientCallback
{
    [OperationContract(IsOneWay = true)]
    Task NotifySomething();
}

クライアントの実装に問題はありません。私の質問は、サービスから呼び出す方法です。これが私がやろうと思っていることです

async void NotifySomething()
{
    try
    {
        await this.callback.NotifySomething();
    }
    catch (AggregateException ex)
    {
        // Unwrap, log the exception(s) and eat it
    }
    catch (Exception ex)
    {
        // Log the exception and eat it
    }
}

さて、誰もがasync void良い習慣ではないと言っているので、ここでそれを使ってもいいですか? 他にどのようなオプションがありますか? WCF サービス コンテキストでこれを実行するための推奨される方法は何ですか?

4

1 に答える 1

5

あなたが書いた方法は、例外を処理するのでかなり安全です。再利用可能な拡張メソッドを作成して、それを繰り返す必要がないようにすることもできます。

おそらく次のようなものです:

public static class Extensions
{
    public static void FireAndForget(this Task task)
    {
        task.ContinueWith(t => 
        {
            // log exceptions
            t.Exception.Handle((ex) =>
            {
                Console.WriteLine(ex.Message);
                return true;
            });

        }, TaskContinuationOptions.OnlyOnFaulted);
    }
}

public async Task FailingOperation()
{
    await Task.Delay(2000);

    throw new Exception("Error");
}   

void Main()
{
    FailingOperation().FireAndForget();

    Console.ReadLine();
}
于 2015-10-31T11:45:24.960 に答える