2011-01-17 52 views
6

Sử dụng .Net 4.0. Tôi có một số mã mà cố gắng để mở một kết nối bằng cách sử dụng BeginConnect và một cuộc gọi lại. Nếu người dùng cố gắng dừng lập trình trong vài khoảnh khắc tiếp theo, tôi cố gắng ngắt kết nối. Tại thời điểm đó tôi thiết lập một lá cờ để cho biết liệu EndConnect có cần phải được gọi từ cuộc gọi lại hay không. Nếu cờ được đặt thành false, tôi bỏ qua EndConnect vì ổ cắm đã được chuyển vào thùng rác.Điều gì sẽ xảy ra nếu bạn không bao giờ gọi Socket.EndConnect?

Tại thời điểm này, người dùng có thể thử kết nối lại ngay lập tức. Tôi không thấy điều này xảy ra nhưng chỉ trong trường hợp. Bây giờ một socket mới được tạo và BeginConnect được gọi lại.

Bạn có bao giờ gọi phương thức EndConnect không?

Trả lời

3

Trong mọi trường hợp (ngoại trừ một [1]) một cuộc gọi đến BeginZZZ cần khớp EndZZZZ phù hợp.

Nếu không, tài nguyên không được quản lý sẽ bị rò rỉ và hoàn toàn có thể hành động ZZZZ sẽ không hoàn thành chính xác — có khả năng làm hỏng việc sử dụng thêm sau đó của ZZZZ sau đó.

Ổ cắm khá mạnh mẽ chống lại sự lạm dụng (ngăn xếp IP phải xử lý các lỗi mạng và các gói không đúng thứ tự), nhưng điều đó không thực hiện tốt.

Nếu bạn đang sử dụng cờ để theo dõi "tắt", tốt hơn là gọi EndConnect và sau đó đóng ngay ổ cắm. Sau khi tất cả các kết nối có thể tự thất bại, và ngắt kết nối không cần thiết (EndConnect ném SocketException). Một cái gì đó như:

mySocket.BeginConnect(address, port, ia => { 
    if (shuttingDown) { 
    try { 
     mySocket.EndConnect(ia); 
     mySocket.BeginDisconnect(false, iaa = { 
     try { 
      mySocket.EndDisconnect(iaa); 
     } catch (Exception) { /* Ignore */ } 
     }, null); 
    } catch (SocketException) { /* Ignore */ } 
    } else { 
    // Normal connection handling 
    } 
}, null); 

Cũng sử dụng ngắt kết nối không đồng bộ để tránh chặn ở đó.


[1] Các ngoại lệ là Control.BeginInvoke trong WinForms, nơi mà các ngoại lệ được ghi nhận một cách rõ ràng.

+0

@Richard. Cảm ơn vì sự trả lời. Tôi đã thử cách tiếp cận của bạn nhưng tôi tiếp tục nhận được ngoại lệ về AsyncResult không giống nhau từ cuộc gọi bắt đầu tương ứng. Tôi đi qua blog của một số anh chàng mà nói rằng chúng ta nên cache AsyncResult và kiểm tra xem nó là như nhau trước khi chúng tôi làm bất cứ điều gì. Điều này có vẻ dodgy và lá tôi trở lại tại điểm khởi đầu anyway. Chỉ cần bỏ qua những điều. – uriDium

+0

@Richard. Được rồi wow. MSDN là rất mơ hồ rửa trên một vài điều. Đầu tiên nó nói: Bạn có thể tạo ra một phương thức gọi lại thực hiện ủy nhiệm AsyncCallback và chuyển tên của nó cho phương thức BeginConnect. Mà thực sự âm thanh như nó là tùy chọn. Sau đó, các đoạn tiếp theo nói: Phương thức gọi lại của bạn nên gọi phương thức EndConnect. Họ chỉ nói với tôi rằng nó là tùy chọn bây giờ họ đang nói với tôi rằng tôi nên gọi EndConnect. Tôi không thể gọi EndConnect nếu tôi "tùy ý" bỏ nó ra. Tuy nhiên: Phần này đã cho tôi hy vọng: Để hủy cuộc gọi đang chờ xử lý sang phương thức BeginConnect, hãy đóng Ổ cắm. – uriDium

+0

@uriDium: Gọi lại là tùy chọn, nhưng gọi 'EndConnect' thì không. Thay vào đó bạn có thể đợi trên 'IAsyncResult' được trả về từ' BeginConnect' (hoặc thăm dò thuộc tính 'IsCompleted') và sau đó gọi' EndConnect' - tất cả mà không cần sử dụng gọi lại. Tóm tắt: 'EndConnect' phải được gọi, nhưng điều này không cần phải nằm trong ủy nhiệm được truyền cho' BeginConnect'. – Richard

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