3

私は、新しい .NET 4.5 CancellationToken メカニズムに基づいて WCF 呼び出しキャンセルを実装する方法を見つけようと、しばらく試みてきました。私が見つけたすべてのサンプルは WCF ベースではなく、サービスの境界を越えていません。

私のサービス:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService
{   
    public void LongOperation()
    {
        // do stuff that takes ages...
        // please cancel me!
    }
}

私のクライアント (デスクトップ アプリ):

自動生成されたプロキシを使用する:

private async void DoLongRunningTaskAsync()
{
    var asyncTask = _myService.LongOperationAsync();
    await asyncTask;
}

このタスクをキャンセルするにはどうすればよいですか? .NET 4.5+ の WCF に適用できる具体的な例を教えてください

編集:

以下の回答は、技術的な理由から不可能であることを示しているようです。したがって、サービスを作成ContextMode=Sessionし、(別のサービス呼び出しで) という静的変数を設定するとcancellationPending=true、元の呼び出しはこの段階でまだ実行されており、定期的にその変数をチェックします。それでもキャンセルできないのでしょうか?それでも無理でしょう?もしそうなら、なぜですか?

4

3 に答える 3

3

前に示したように。サーバー側でサービス境界を越えてキャンセルすることはできません。

クライアント側でタスクをキャンセルする場合は、 Microsoft.VisualStudio.Threading.ThreadingToolsWithCancellationの拡張メソッドを使用できます。

これはVisual Studio SDKの一部であるか、 Nugetから入手することもできます。

 CancellationTokenSource ct = new CancellationTokenSource();
 ct.CancelAfter(20000);
 var asyncTask = _myService.LongOperationAsync();
 await asyncTask.WithCancellation(ct.Token);
于 2015-10-28T16:37:52.770 に答える
1

質問を編集した後、論理レベルをキャンセルしても問題ないことがわかりました。その場合、次のアルゴリズムを試すことができます。

1) を使用してサービスを作成しますInstanceContextMode=InstanceContextMode.PerSession。これにより、後続のリクエストを処理するために同じサービス インスタンスが保証されます。

2) 新しいセッションを開始するには、 でマークされたサービス操作を使用しますOperationContract(IsInitiating = True)

3) サービスメンバーとして作成します。静的ではありません。サービス状態になります

CancellationTokenSource ct = new CancellationTokenSource();

4) すべてのサービス メソッド内で、タスク内で新しい計算を開始し、このタスクのパラメーターとしてキャンセル トークンを配置する必要があります。

[ServiceContract(SessionMode = SessionMode.Allowed)]
public interface ICalculator
{
   [OperationContract(IsInitiating = True)]
   Bool Begin()

   [OperationContract(IsInitiating = false)]
   double Add(double n1, double n2)
}

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculatorService : ICalculator
{
    CancellationTokenSource cts = new CancellationTokenSource();

    public double Add(double n1, double n2)
    {
        var cancellationToken = cts.Token;

        var t = Task<double>.Factory.StartNew(() => { 
           // here you can do something long
           while(true){
           // and periodically check if task should be cancelled or not
           if(cancellationToken.IsCancellationRequested)
             throw new OperationCanceledException();

           // or same in different words
           cancellationToken.ThrowIfCancellationRequested();
           }
           return n1 + n2;
        }, cancellationToken);

        return t.Result;
    }

    public Bool Begin(){}
}

ここでは、 WCF セッションについて簡単に説明します。

すべての例は私の頭からのものであり、実際に機能するかどうかは試していません。しかし、あなたは試すことができます。

于 2015-10-29T14:49:52.347 に答える