2008-09-18 34 views
14

Tôi có một ứng dụng Silverlight 2 đang sử dụng dịch vụ WCF. Như vậy, nó sử dụng các cuộc gọi lại không đồng bộ cho tất cả các cuộc gọi đến các phương thức của dịch vụ. Nếu dịch vụ không chạy hoặc bị treo hoặc mạng bị trục trặc, vv trước hoặc trong một trong các cuộc gọi này, ngoại lệ được tạo như bạn mong đợi. Vấn đề là, tôi không biết cách bắt ngoại lệ này.Cách tốt nhất để bắt ngoại lệ WCF trong Silverlight là gì?

  • Vì đây là cuộc gọi không đồng bộ, tôi không thể kết thúc cuộc gọi bắt đầu bằng khối try/catch và nhận ngoại lệ sau khi chương trình đã chuyển từ điểm đó.

  • Vì proxy dịch vụ được tạo tự động, tôi không thể đặt khối try/catch trên mỗi và mọi hàm được tạo gọi EndInvoke (nơi ngoại lệ thực sự xuất hiện). Các hàm được tạo này cũng được bao quanh bởi Mã ngoài trong ngăn xếp cuộc gọi, vì vậy không có nơi nào khác trong ngăn xếp để đặt thử/bắt.

  • Tôi không thể đặt thử/nắm bắt trong các hàm gọi lại của mình, vì ngoại lệ xảy ra trước khi chúng được gọi.

  • Có một hàm Application_UnhandledException trong App.xaml.cs của tôi, nó nắm bắt tất cả các ngoại lệ chưa được xử lý. Tôi có thể sử dụng điều này, nhưng nó có vẻ như một cách lộn xộn để làm điều đó. Tôi muốn dành chức năng này cho các lỗi thực sự bất ngờ (hay còn gọi là lỗi) và không kết thúc bằng mã trong hàm này cho mọi hoàn cảnh mà tôi muốn giải quyết theo một cách cụ thể.

Tôi có thiếu giải pháp rõ ràng không? Hoặc tôi bị mắc kẹt bằng cách sử dụng Application_UnhandledException?

[Chỉnh sửa]
Như đã đề cập bên dưới, thuộc tính Lỗi chính xác là những gì tôi đang tìm kiếm. Điều gì đang ném tôi cho một vòng lặp là một thực tế là ngoại lệ được ném và dường như không bị bắt, nhưng thực hiện có thể tiếp tục. Nó kích hoạt sự kiện Application_UnhandledException và làm cho VS2008 phá vỡ việc thực hiện, nhưng việc tiếp tục trong trình gỡ rối cho phép thực hiện tiếp tục. Nó không thực sự là một vấn đề, nó chỉ có vẻ kỳ quặc.

Trả lời

12

Tôi kiểm tra thuộc tính Lỗi của sự kiện args trong phương thức xử lý sự kiện đã hoàn tất dịch vụ. Tôi chưa gặp vấn đề với trình xử lý sự kiện không được gọi. Trong trường hợp máy chủ bị hỏng, cuộc gọi sẽ mất vài giây rồi quay trở lại với một ProtocolException trong thuộc tính Lỗi.

Giả sử bạn đã thử điều này và gọi lại của bạn thực sự không bao giờ được gọi, bạn có thể xem xét tùy chỉnh lớp proxy đã tạo. Xem this article.

+0

Chỉ cần làm rõ, "gọi lại phương thức dịch vụ" nghĩa là sự kiện đã hoàn thành phương thức, không phải là gọi lại. Gọi lại được sử dụng với APM, trong khi Silverlight sử dụng EAP. –

+0

Đồng ý. Cập nhật cho phù hợp. – dcstraw

5

Tôi đã tìm thấy a forum thread đang nói về điều này và đề cập rằng thực hành tốt nhất là sử dụng thuộc tính Lỗi. Giữa chủ đề này và kinh nghiệm của riêng tôi, đây là những gì tôi có thể kết luận:

  • Trong mã NET bình thường, lớp proxy tạo ra xử lý các ngoại lệ đúng bằng cách đặt ngoại lệ trong tài sản Lỗi thay vì ném nó.

  • Trong Silverlight, lớp proxy được tạo sẽ đặt thuộc tính Lỗi, nhưng không xử lý hoàn toàn ngoại lệ. Ngoại lệ được chọn bởi trình gỡ lỗi, bật lên hộp ngoại lệ với thông báo "ProtocolException đã bị hủy bỏ bởi mã người dùng". Mặc dù thông báo này, ngoại lệ dường như không thực sự làm cho nó thành hàm Application_UnhandledException.

Tôi mong rằng đây là một trong những điều họ sẽ khắc phục trong bản phát hành cuối cùng.

Hiện tại, tôi sẽ sử dụng thuộc tính Lỗi và chỉ xử lý việc thực thi vi phạm trình gỡ lỗi. Nếu nó quá khó chịu, tôi có thể tắt ngắt ngoại lệ cho ProtocolException.

0

Bạn có thể quên đi Application_UnhandledException trên callbacks client asyn, lý do tại sao:

Application_UnhandledException chỉ ngoại lệ bắn vào thread UI thể được đánh bắt bởi Application.UnhandledExceptions

Điều này có nghĩa ... không được gọi vào tất cả cho một cuộc gọi không đồng bộ WCF :-).

Kiểm tra phản ứng chi tiết từ MSFT

http://silverlight.net/forums/t/21828.aspx

Xin chào, chỉ trường hợp ngoại lệ bắn vào thread UI thể được đánh bắt bởi Application.UnhandledExceptions. Nó không thể bắt ngoại lệ từ các chủ đề khác. Bạn có thể thử vấn đề này để giải quyết vấn đề: Trong Visual Studio, từ trình đơn Debug, chọn Ngoại lệ. Sau đó kiểm tra "Ngoại lệ thời gian chạy ngoại ngữ". Điều này sẽ làm cho trình gỡ lỗi dừng lại bất cứ khi nào một ngoại lệ được ném ra. Nhưng lưu ý điều này có thể khá khó chịu đôi khi kể cả khi một ngoại lệ đã bị bắt. Bạn có thể sử dụng các hộp kiểm để lọc các ngoại lệ mà bạn muốn nắm bắt.

Tin tốt trong trường hợp của tôi là việc xử lý thông báo lỗi chỉ trong dịch vụ gọi lại clietn là đủ nếu bạn không gỡ lỗi.

Cảm ơn

Braulio 
+3

Đây không phải là trường hợp. Tôi chắc chắn nhấn Application_UnhandledExceptions khi ngoại lệ bắt nguồn từ dịch vụ WCF. Tôi có thể nói vì tôi có thể dễ dàng kiểm tra FaultException đã được ném. – Rire1979

0

OOpps ....

câu trả lời sai Xin lỗi từ phía tôi (cũng anh chàng MSFT đã không tung ra dịch vụ ghi câu trả lời callbacks được gọi là trên thread UI giống nhau), vấn đề là

Thông tin thêm:

- In development even detaching from the debugger, this method is never reached. 
- On the production environment yes. 

tôi đoán điều gì đó liên quan với Visu al Studio tùy chọn và chặn ngoại lệ.

Thông tin thêm, trong chủ đề này http://silverlight.net/forums/p/48613/186745.aspx#186745

chủ đề Khá thú vị.

0

Tôi không phải là thợ sửa ống nước, vì vậy tôi quyết định tạo lớp dịch vụ WCF của riêng tôi ghi đè một số chức năng của tệp lớp "reference.cs" được tạo tự động bởi Visual Studio, sau đó tôi đã thêm thử của riêng mình/bắt khối để bắt lỗi giao tiếp.

Lớp tôi tạo ra trông giống như sau:

public class myWCFService : MyWCFServiceClient 
{ 

    protected override MyController.MyService.IMyWCFService CreateChannel() 
    { 
     return new MyWCFServiceClientChannel(this); 
    } 

} 

private class MyWCFServiceClientChannel : ChannelBase<MyController.MyService.IMyWCFService>, MyController.MyService.IMyWCFService 
{ 
    /// <summary> 
    /// Channel Constructor 
    /// </summary> 
    /// <param name="client"></param> 
    public MyWCFServiceClientChannel(System.ServiceModel.ClientBase<MyController.MyService.IMyWCFService> client) : 
    base(client) 
    { 
    } 
    /// <summary> 
    /// Begin Call To RegisterUser 
    /// </summary> 
    /// <param name="memberInformation"></param> 
    /// <param name="callback"></param> 
    /// <param name="asyncState"></param> 
    /// <returns></returns> 
    public System.IAsyncResult BeginRegisterUser(MyDataEntities.MembershipInformation memberInformation, System.AsyncCallback callback, object asyncState) 
    {    
     object[] _args = new object[1]; 
     _args[0] = memberInformation; 
     System.IAsyncResult _result = base.BeginInvoke("RegisterUser", _args, callback, asyncState); 
     return _result;    
    } 
    /// <summary> 
    /// Result from RegisterUser 
    /// </summary> 
    /// <param name="result"></param> 
    /// <returns></returns> 
    public MyDataEntities.MembershipInformation EndRegisterUser(System.IAsyncResult result) 
    { 
     try 
     { 
      object[] _args = new object[0]; 
      MyDataEntities.MembershipInformation _result = ((MyDataEntities.MembershipInformation)(base.EndInvoke("RegisterUser", _args, result))); 
      return _result; 
     } 
     catch (Exception ex) 
     { 
      MyDataEntities.MembershipInformation _result = new MyDataEntities.MembershipInformation(); 
      _result.ValidationInformation.HasErrors = true; 
      _result.ValidationInformation.Message = ex.Message; 
      return _result; 
     } 
    } 
} 
+1

Tại sao đi đến tất cả các nỗ lực này, chỉ để vứt bỏ tất cả các phần của ngoại lệ khác với tài sản Message? Nó gần như không bao giờ là một ý tưởng tốt để vứt bỏ thông tin. –

+0

Những gì John nói. StackTrace và InnerException đặc biệt hữu ích. – MetalMikester

0

Với Silverlight 3 các debugger Visual Studio bắt những trường hợp ngoại lệ để xử lý ngoại lệ - mức gây nhầm lẫn - không bao giờ đạt được.Tuy nhiên, khi chạy mà không cần trình gỡ rối, trình xử lý ngoại lệ được gọi như mong đợi. Tôi đoán điều này là ok miễn là người ta nhận thức được nó. Tôi thừa nhận tôi lãng phí một vài giờ cố gắng tìm ra cách để khoan vào các hoạt động bên trong của Silverlight/Wcf/Browser để có được ngoại lệ của tôi. Đừng đi đến đó.

0

Sử dụng trình tạo proxy WCF tùy chỉnh là một giải pháp tốt để xử lý ngoại lệ không đồng bộ trong Silver-light.Click here để tải xuống mã nguồn.

0

Với XNA trên WP7, tôi thấy mình không có lựa chọn nào khác ngoài việc thêm thủ công/bắt các phương thức async End * FunctionName *() khác nhau; không có gì khác tôi đã cố gắng sẽ ngăn chặn lỗi ứng dụng & tắt khi máy chủ không khả dụng. Đó là một sự cố thực sự phải cập nhật mã này theo cách thủ công khi dịch vụ thay đổi.

Tôi ngạc nhiên đây không phải là vấn đề lớn vì dường như không có cách nào khác để nắm bắt các ngoại lệ này trên WP7 bằng XNA nhưng tôi cho rằng điều này chỉ nói về số lượng (== không nhiều) người đang cố gắng làm điều này hơn bất cứ điều gì khác. Nếu họ chỉ làm slsvcutil.exe tạo ra các phương thức đồng bộ, chúng ta có thể dễ dàng nắm bắt chúng trong chuỗi nhân viên của chúng ta, nhưng tiếc là mã được tạo ra sử dụng các luồng thread thread mà không có phương tiện để bắt các ngoại lệ.

0

Để xử lý tình huống này, hãy sử dụng TargetInvocationException. Điều này sẽ bắt ngoại lệ khi mạng bị ngắt hoặc dịch vụ của bạn không khả dụng.

Các vấn đề liên quan