簡體   English   中英

如何取消異步WCF調用?

[英]How to cancel an async WCF call?

我一直在嘗試一些時間,以了解如何基於新的.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 ,我的原始調用在此階段仍在運行,並且會定期檢查該變量。 我仍然無法取消嗎? 還是不可能嗎? 如果是這樣,為什么?

如前所述。 跨越服務邊界並在服務器端取消是不可能的。

如果要在客戶端取消任務,則可以使用Microsoft.VisualStudio.Threading.ThreadingTools的擴展方法WithCancellation

它是Visual Studio SDK的一部分,或者您也可以從Nuget獲取它。

 CancellationTokenSource ct = new CancellationTokenSource();
 ct.CancelAfter(20000);
 var asyncTask = _myService.LongOperationAsync();
 await asyncTask.WithCancellation(ct.Token);

用兩個詞來說-這是不可能的。

如果您了解WCF調用的本質,那么它將變得顯而易見。

看您的示例,我們通常會看到:通過網絡連接的兩台單獨的機器A和B。 在機器A上,您有一些偵聽套接字的組件,當它收到命令時,它將啟動同步長計算RemoteCall()

在計算機B上,您有一個實際上具有兩個自動生成方法的客戶端

BeginRemoteCall->IAsyncResult + EndRemoteCall(IAsyncResult)

本質上,新的基於任務的異步調用版本(aka RemoteCallAsync()->Task )完全相同,並且您始終可以使用TaskFactory.FromAsync(BeginRemoteCall,EndRemoteCall)->Task創建自己的任務

當您在客戶端上調用BeginRemoteCall時,將命令發送到第二台計算機“請開始計算”,然后添加一個回調,在完成計算並得出結果時將調用該回調。 在內部,此異步實現使用I / O完成端口,並允許您的客戶端處於非阻塞狀態。

但是,如果已經開始,則無法取消服務器端的操作。 您可能對結果不感興趣,可以忽略回調,但是無論如何,服務器端的計算將完成。

而已

編輯問題后,我看到取消邏輯級別是可以接受的。 如果是這樣,可以嘗試以下算法。

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會話的快速描述

所有示例均來自我的腦海,尚未嘗試過是否真的有效。 但是您可以嘗試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM