2010-12-12 11 views
7

Tôi có kiến ​​trúc 3 tầng và gửi một số dữ liệu trong lớp vận chuyển (TCP Client) bằng cách sử dụng các ổ cắm tcp là phương pháp này không đồng bộ bằng phương pháp BeginSend.Lỗi ngoại lệ bị lỗi từ một cuộc gọi lại C#

public void TransportData(Stream stream) 
{ 
    try 
    { 
     SetTransporterState(StateObject.State.SendingData); 
     if (clientSock.Connected) 
     { 
      ASCIIEncoding asen = new ASCIIEncoding(); 
      stream.Position = 0; 
      byte[] ba = GetStreamAsByteArray(stream); 
      if (clientSock.Connected) 
       clientSock.BeginSend(ba, 0, ba.Length, SocketFlags.None, new AyncCallback(SendData), clientSock); 
      else 
       throw new SockCommunicationException("Socket communication failed"); 

     } 
     catch (SocketException sex) 
     { 
      throw sex; 
     } 
     catch (SockCommunicationException comex) 
     { 
      bool rethrow = ExceptionPolicy.HandleException(comex, "TransportLayerPolicy"); 
     if (rethrow) 
     { 
      throw; 
     } 
     } 
    } 
    } 
    catch (SocketException soex) 
    { 
    throw soex; 
    } 
    catch (SockCommunicationException comex) 
    { 
     bool rethrow = ExceptionPolicy.HandleException(comex, "TransportLayerPolicy"); 
     if (rethrow) 
     { 
     throw; 
     }     
    } 
    catch (Exception ex) 
    { 
     LoggingMessageHelper.LogDeveloperMessage(ex.Message + Environment.NewLine + ex.StackTrace, 1, TraceEventType.Critical); 
     bool rethrow = ExceptionPolicy.HandleException(ex, "TransportLayerPolicy"); 
     if (rethrow) 
     { 
      throw; 
     } 
    } 
    } 

Mã callback SendData() là dưới

private void SendData(IAsyncResult iar) 
    { 
     Socket remote = null; 
     try 
     { 
      remote = (Socket)iar.AsyncState; 
      try 
      { 
       int sent = remote.EndSend(iar); 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 

      if (remote.Connected) 
      { 
       remote.BeginReceive(data, 0, size, SocketFlags.None, 
           new AsyncCallback(ReceiveData), remote); 
      } 
      else 
       throw new SockCommunicationException("Communication Failed"); 
     } 
     catch (SocketException soex) 
     { 
      throw new SockCommunicationException("Communication Failed"); 
     } 
     catch (SockCommunicationException comex) 
     { 
      bool rethrow = ExceptionPolicy.HandleException(comex, "TransportLayerPolicy"); 
      if (rethrow) 
      { 
       throw; 
      } 
     } 

Khi ngắt kết nối máy chủ, khách hàng không biết cho đến khi nó sẽ gửi một số dữ liệu, do đó tài sản được kết nối đúng. Sau đó, dòng từ xa.BeginReceive() ném SocketException mà tôi cố gắng để nắm bắt và ném một ngoại lệ tùy chỉnh (sockCommunicationException).

Tuy nhiên, khi tôi làm điều này, tôi nhận được một ngoại lệ chưa được giải quyết. Tôi muốn bong bóng lỗi này tới giao diện người dùng thông qua lớp Doanh nghiệp. Khi một ngoại lệ như thế này được nâng lên trong phương thức gọi lại, nó được nâng lên đến đâu?

Làm cách nào để tránh ngoại lệ chưa xử lý này và bong bóng ngoại lệ này lên lớp Giao diện người dùng.

Vui lòng trợ giúp.

Cảm ơn trước!

Trả lời

2

Đây là yêu cầu chung.

Giải pháp thường bằng cách SendData có quyền truy cập vào một số phương pháp cục bộ để thông báo cho khách hàng về kết quả hoạt động và có thể hiển thị trong giao diện người dùng.

Bây giờ, bạn cần đạt được điều này ở mức trung bình tầng giữakhác nhau. Máy khách của bạn gọi máy chủ mà lần lượt gọi phương thức không đồng bộ và kích hoạt hoạt động. Nếu khách hàng cần biết về kết quả và ngoại lệ của nó, nó phải thăm dò ý kiến ​​ máy chủ và kiểm tra kết quả - và bạn sẽ phải lưu trữ kết quả (trên máy chủ hoặc một số cơ sở dữ liệu) cho đến khi khách hàng truy xuất hoặc vứt bỏ sau khi hết thời gian - việc dọn dẹp trở nên phức tạp.

Hoặc có thể sử dụng phương pháp Duplex để Máy chủ liên lạc lại với Máy khách. Giải pháp này nghe có vẻ tuyệt vời nhưng công bằng là khủng khiếp vì nhiều lý do nằm ngoài phạm vi của câu hỏi này.

+0

Xin chào Aliostad, Vì vậy, bạn có nói rằng tôi có một đại biểu trong tầng giao vận và nâng cao một sự kiện được đăng ký bởi lớp kinh doanh khi lỗi này xảy ra? – user466898

+0

Không, cách tiếp cận ưa thích của tôi là dành cho khách hàng để thăm dò ý kiến ​​máy chủ nếu nó ** có ** để biết kết quả. – Aliostad

+0

Tôi xin lỗi vì tôi không hiểu. Nếu trước đây tôi chưa giải thích rõ ràng, máy khách gửi yêu cầu và máy chủ trả lời lại với lỗi rằng nó đã ngắt kết nối máy khách. Đó là lý do tại sao tôi nhận được socketexception lớn lên với thông báo "Một kết nối được thiết lập đã bị hủy bỏ bởi phần mềm trong máy chủ của bạn" và mã lỗi "10053". Tôi nhận được lỗi này ném chỉ trong dòng từ xa.BeginReceive() trong phương pháp gọi lại. Tôi chỉ cần bong bóng lên trên. – user466898

3

Có, không hoạt động. Gọi lại được thực hiện trên một thread threadpool, không có ai ở đó để bắt ngoại lệ. Bạn sẽ cần phải nói, nâng cao một sự kiện mà giao diện người dùng có thể đăng ký. Yêu cầu Marshaling, mã UI cần sử dụng một cái gì đó như Control.BeginInvoke() nếu nó cần cập nhật giao diện người dùng.

+0

Cảm ơn, tôi có thể xử lý nó khi nói đến giao diện người dùng bằng cách kiểm tra xem InvokeRequired và xử lý nó cho phù hợp bằng cách sử dụng một đại biểu. Đang tăng sự kiện là phương pháp tốt nhất để bong bóng lỗi lên đến lớp doanh nghiệp và từ đó đến giao diện người dùng? – user466898

+1

Đối với các lỗi không đồng bộ, có. –

+0

Ok ... Cảm ơn một lần nữa Hans !. Tôi đã suy nghĩ nếu có một số được xây dựng trong phương pháp trong khuôn khổ NET để xử lý một cái gì đó như thế này mà không cần sử dụng các sự kiện. – user466898