2012-04-13 24 views
10

Xem xét phương thức Socket.BeginSend(). Nếu hai thread thread thread được gọi phương thức này cùng một lúc, liệu các thông điệp tương ứng của chúng có kết thúc với nhau hay không, lớp socket giữ cho điều này xảy ra?Có phải không đồng bộ ghi vào một ổ cắm an toàn không?

+1

Trong khi nó hoạt động, bạn chỉ nên thực hiện với giao thức dựa trên datagram đặt hàng không đáng tin cậy như UDP. Lý do là nếu hai chủ đề chạy đua để gọi BeginSend, bạn có thể nhận được ra lệnh gửi tại nguồn. Điều này sẽ dẫn đến hỏng dữ liệu ứng dụng khi sử dụng TCP. –

Trả lời

7

Tôi đã tìm thấy một số post on the MSDN forum quen thuộc dường như trả lời cho câu hỏi của bạn.

  1. Bạn có thể xếp hàng nhiều BeginSends cùng một lúc. Bạn không cần phải khóa

Edit:

thông tin Thậm chí thú vị hơn:

Nếu bạn cuộn xuống một chút trong Remark section of the MSDN doc BeginSend(), bạn sẽ tìm thấy sử dụng thú vị của callback các phương pháp có thể phù hợp với bạn.

[...] Nếu bạn muốn chuỗi ban đầu chặn sau khi bạn gọi phương thức BeginSend, hãy sử dụng phương thức WaitHandle.WaitOne. [...]

+1

Tôi không biết điều này, cảm ơn! – covertCoder

+1

Đây chính xác là những gì tôi đang tìm kiếm! CẢM ƠN! – Dabloons

11

Trường hợp ổ cắm .NET không an toàn chỉ trong các cuộc gọi đồng thời tới một số phương thức (cùng hoặc các phương thức khác) có thể gây ra trạng thái không nhất quán. Tuy nhiên, các phương pháp BeginSend()BeginReceive() an toàn theo chủ đề đối với chính chúng.

Có thể thực hiện nhiều cuộc gọi chưa thực hiện cho mỗi (hoặc cả hai).

Trong trường hợp BeginReceive(), chúng sẽ được bảo dưỡng khi dữ liệu có sẵn theo thứ tự được gọi. Điều này có thể hữu ích nếu, ví dụ, xử lý của bạn là dài nhưng bạn muốn nhận được khác xảy ra càng nhanh càng tốt. Tất nhiên trong trường hợp này bạn có thể có mã của bạn xử lý nhiều biên lai cùng một lúc và bạn có thể cần logic đồng bộ hóa của riêng bạn để bảo vệ trạng thái ứng dụng của bạn.

Trong trường hợp BeginSend(), mỗi cuộc gọi sẽ cố đẩy dữ liệu đã gửi vào bộ đệm ổ cắm và ngay khi được chấp nhận ở đó, cuộc gọi lại của bạn sẽ được gọi (nơi bạn sẽ gọi EndSend()). Nếu không có đủ dung lượng bộ đệm cho bất kỳ cuộc gọi nào, nó sẽ chặn.

Lưu ý: đừng cho rằng bộ đệm mặc định 8k có nghĩa là "tôi có thể nhanh chóng gọi BeginSend() với chính xác 8k dữ liệu, sau đó nó sẽ chặn", như sau đây là đúng:

  1. Các 8K là một "kích thước danh nghĩa" số, và bộ đệm có thể co lại và phát triển hơi

  2. Khi bạn đang queing lên đáng 8K cuộc gọi, dữ liệu sẽ được được gửi trên mạng giảm mà 8K dữ liệu xếp hàng đợi

Nói chung:

  • Nếu bạn gọi BeginSend() nhiều lần trong một chủ đề, bạn được đảm bảo rằng sẽ gửi sẽ rời khỏi máy theo thứ tự chúng được gọi.

  • Nếu bạn gọi BeginSend() từ một số chủ đề, không đảm bảo đơn đặt hàng trừ khi bạn sử dụng một số cơ chế chặn khác để buộc các cuộc gọi thực sự xảy ra theo một số thứ tự cụ thể. Tuy nhiên, mỗi cuộc gọi sẽ gửi dữ liệu của nó đúng trong một luồng byte liền kề.

+0

Câu trả lời của bạn đã đến một vài năm sau câu hỏi ban đầu và tôi vừa mới thấy nó (một năm sau) nhưng tôi muốn bạn biết rằng nó có chi tiết tuyệt vời và tôi thực sự đánh giá cao nó. Mặc dù, kiến ​​thức cá nhân của riêng tôi về khuôn khổ .Net và kỹ năng của tôi là một nhà phát triển đã vượt qua câu hỏi này ngay bây giờ, câu trả lời này sẽ là một nguồn tài nguyên tuyệt vời cho người đọc trong tương lai. Nếu tôi chưa kiểm tra câu trả lời đúng như câu trả lời đúng năm trước, tôi sẽ trả lời đúng cho bạn. Nhiều đánh giá cao. – Dabloons

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