2013-10-10 78 views
0

我努力學習WCF,所以我用簡單的WCF應用程序中播放,從來源斯蒂芬·克利裏=>async-wcf-today-and-tomorrow在客戶端WCF異步...失去了異常

以下是代碼片段:

簡單合同:

[DataContract] 
public class CalculatorFault 
{ 
    [DataMember] 
    public string Message { get; set; } 
} 

[ServiceContract] 
public interface ICalculator 
{ 

    [OperationContract] 
    [FaultContract(typeof(CalculatorFault))] 
    Task<uint> DivideAsync(uint numerator, uint denominator); 
} 

簡單的服務實現:

public class Calculator : ICalculator 
{ 
    public async Task<uint> DivideAsync(uint numerator, uint denominator) 
    { 
    try 
    { 
     var myTask = Task.Factory.StartNew(() => numerator/denominator); 
     var result = await myTask; 
     return result; 
    } 
    catch (DivideByZeroException) 
    { 
     throw new FaultException<CalculatorFault>(new CalculatorFault { Message = "Undefined result" }); 
    } 
    } 
} 

和客戶端的簡單呼叫:

static class Program 
{ 
    static async Task CallCalculator() 
    { 
    try 
    { 
     var proxy = new CalculatorClient(); 
     var task = proxy.DivideAsync(10, 0); 
     var result = await task; 
     Console.WriteLine("Result: " + result); 
    } 
    catch (FaultException<CalculatorFault> ex) 
    { 
     Console.Error.WriteLine("Error: " + ex.Detail.Message); 
    } 
    } 

    static void Main(string[] args) 
    { 
    try 
    { 
     CallCalculator().Wait(); 
    } 
    catch (Exception ex) 
    { 
     Console.Error.WriteLine(ex); 
    } 

    Console.ReadKey(); 
    } 
} 

它的工作原理:當我嘗試用零除數時,我得到了來自客戶端的異常。

但我想要做的是委託調用WCF像老回調等功能functions.So我嘗試以下方法,在客戶端

async Task CallCalculator() 
{ 
    try 
    { 
     var task = channel.DivideAsync(10, 0); 
     task.ContinueWith(OnWorkCompleted); 
    } 
    catch (FaultException<CalculatorFault> ex) 
    { 
     Console.Error.WriteLine("Error: " + ex.Detail.Message); 
    } 

} 

void OnWorkCompleted(Task<uint> task) 
{  
    var result = task.Result; 
    Console.WriteLine("Result From Async: " + result); 
} 

而這也可以,但是當我嘗試嘗試除以零,我沒有例外,雖然服務拋出異常,但客戶端沒有結果。

爲什麼會發生這種情況?我如何解決它以從客戶端捕獲異常?

回答

3

作爲一般規則,不要在async代碼中使用ContinueWith;您應該使用await

當您調用task.Result時,您的代碼實際上正在發生異常,但CallCalculator中的catch塊無法捕獲此異常。

所以,我會做這樣的事情:

async Task CallCalculator() 
{ 
    try 
    { 
    var result = await channel.DivideAsync(10, 0); 
    OnWorkCompleted(result); 
    } 
catch (FaultException<CalculatorFault> ex) 
    { 
    Console.Error.WriteLine("Error: " + ex.Detail.Message); 
    } 
} 
+0

什麼都.NET 4個的用戶也,如果他們不能使用等待? –

+0

@OvidiuBuligan:對於除ASP.NET以外的所有.NET 4.0場景,我推薦'Microsoft.Bcl.Async'。 –

+0

對不起,提出另一個稍微相關的問題。如果您想爲目標框架設置爲.net 4的項目創建代理,則「生成基於異步的任務」變爲灰色。我通過在.net 4.5上生成基於任務的異步並用一些bat腳本切換回4.0來從生成的xml中刪除一行來欺騙它。而且,儘管我可以看到,它仍然有效。你知道他們爲什麼在項目目標運行時間爲4.0時變灰了嗎? (我正在使用vs 2013 express for desktop) –