2011-01-11 30 views
7

Bạn có thể xử lý nặng trong các cuộc gọi lại không đồng bộ của .NET hay không, hãy lưu chúng trong nhiều giây trước khi trở về? Hay tôi đang tước HĐH/thời gian chạy của các tài nguyên quan trọng?OK để xử lý nặng trong các cuộc gọi lại không đồng bộ?

Ví dụ: xem xét TcpListener.BeginAcceptSocket. Gọi lại của tôi bắt đầu bằng cách gọi EndAcceptSocket, sau đó dành một thời gian nhận dữ liệu và chỉ sau đó đóng socket và trả về. Đây có phải là cách nó được sử dụng, hoặc tôi dự kiến ​​sẽ thực hiện việc xử lý thêm trên chủ đề của riêng tôi?

+0

tôi sẽ mong bạn hãy nhìn vào Rx (phần mở rộng Reactive) mà làm cho chương trình không đồng bộ một buổi tối đi dạo trong một công viên xinh đẹp! http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx – gideon

+0

Một số liên kết Rx hữu ích: http://rxwiki.wikidot.com/ Đây là mã nhỏ tôi đã viết để cập nhật không đồng bộ một hộp danh sách mỗi khi tôi nhập trong hộp văn bản và tăng tốc độ bằng 0,5 giây. Xem-> http://stackoverflow.com/questions/4655619/simple-rx-code-silently-fails-in-windows-forms-only-during-debugging-in-visual-st – gideon

Trả lời

1

Có, đây là cách Ổ cắm không đồng bộ (máy khách Tcp, trình nghe, v.v.) được thiết kế để sử dụng. Bạn nên luôn luôn đảm bảo rằng bạn gọi phương thức aysnc kết thúc và sau đó thực hiện bất kỳ việc xử lý nào bạn mong muốn. Không yêu cầu các phương thức EndAccept(), EndSEnd(), EndReceive(), v.v., để lại cho bạn khả năng bị rò rỉ bộ nhớ, vì vậy nó luôn luôn là một thực hành tốt để làm theo.

Các chủ đề được sử dụng không khác gì nếu bạn đã tự tạo một luồng nền theo cách thủ công và được sử dụng cho cả "hoạt động dài hạn" trong vài giây. Tôi tin tưởng, bạn không muốn bất cứ điều gì mà phải mất lâu để được chạy trên một thread dispatching hoặc GUI.

Tôi có trên 90 hệ thống dựa trên thiết bị di động sử dụng Ổ cắm không đồng bộ cho máy chủ và thực hiện công việc tuyệt vời: nhanh hơn nhiều so với dịch vụ web (nhớ tất cả giao thức web chạy trên đầu Ổ cắm), dễ phát hiện lỗi v.v. Bạn sẽ phải làm một Google trên nó, nhưng có một anh chàng đã xuất bản thử nghiệm của mình bằng cách sử dụng công nghệ này và ông đã có thể hỗ trợ 1.000 truyền thông đồng thời đến một máy chủ chỉ với 11 chủ đề. Không tệ.

server ví dụ từ MS: http://msdn.microsoft.com/en-us/library/fx6588te.aspx

khách hàng ví dụ từ MS: http://msdn.microsoft.com/en-us/library/bew39x2a.aspx

Phải mất hơn những để có được nó "hoàn thiện" nhưng đây là một nơi tốt để bắt đầu.

+1

Bài viết tại http: // www.codeproject.com/KB/threads/threadtests.aspx dường như chỉ ra rằng .NET ThreadPool có các vấn đề về hiệu năng nếu bạn xử lý lâu trong các luồng thread (chẳng hạn như các trình xử lý hoàn thành cuộc gọi không đồng bộ). Vấn đề này có được hiển thị cho bạn không? – Sander

+0

Tôi thực sự không thể nói chuyện với thời gian xử lý thực sự lâu dài, nhưng từ quan điểm truyền thông Socket, chúng tôi chưa bao giờ gặp bất kỳ vấn đề gì. Tất cả các thông tin liên lạc của chúng tôi đều tuân theo phương pháp tiếp cận asynch đệm, và thậm chí truyền tải lớn ... cho biết một gói dữ liệu, trên nền tảng di động có thể mất nhiều thời gian, miễn là mạng chắc chắn Ổ cắm đã được chứng minh là đáng tin cậy. Trớ trêu thay chỉ là về mọi công nghệ mạng truyền thông sử dụng Sockets bên dưới một trừu tượng cao hơn để xử lý việc nâng hạng nặng (thường không có sẵn trong di động). – BonanzaDriver

+0

@Sander: Vào năm 2003, ThreadPool có mặc định là 25 luồng cho mỗi CPU trong đó (và hầu hết các máy tính là lõi đơn). Bây giờ mặc định là 250 cho mỗi CPU vì vậy có ít vấn đề hơn có sử dụng được: http://msdn.microsoft.com/en-us/library/system.threading.threadpool(v=VS.90).aspx (và .net 4 mang nó lên đến 1023 cho mỗi CPU trên 32 bit và 32768 cho mỗi CPU trên 64 bit!) –

1

Tôi lặp lại các thí nghiệm của CodeProject article on this topic và nhận thấy kết quả cho .NET 4 tương tự như được mô tả trong năm 2003. Lưu ý rằng bài viết không thực sự liệt kê các kết quả cho phần có vấn đề nhưng tôi hiểu nó chính vấn đề vẫn tồn tại.

Tôi đã sử dụng lại mã này từ bài viết CodeProject - chỉ cần tải xuống để chạy thử nghiệm này hoặc thử nghiệm.

Thử nghiệm sẽ cố gắng sử dụng 10 chuỗi song song để đếm cao nhất có thể trong 1 giây.

Sử dụng 10 đề nền (ví dụ new Thread())

 
T0 = 4451756 
T1 = 4215159 
T2 = 5449189 
T3 = 6244135 
T4 = 3297895 
T5 = 5302370 
T6 = 5256763 
T7 = 3779166 
T8 = 6309599 
T9 = 6236041 
Total = 50542073 

Sử dụng hạng mục công trình 10 ThreadPool

 
T0 = 23335890 
T1 = 20998989 
T2 = 22920781 
T3 = 9802624 
T4 = 0 
T5 = 0 
T6 = 0 
T7 = 0 
T8 = 0 
T9 = 0 
Total = 77058284 

Lưu ý rằng chỉ có 4 chủ đề công việc hồ bơi mặt hàng trong số 10 từng bị hành quyết trong lát thời gian 1 giây! Đây là trên một CPU quad-core, do đó, đó là một sợi cho mỗi lõi.Các nhiệm vụ khác được thực hiện sau khi hoàn thành bốn lệnh đầu tiên và do 1 giây được phân bổ đã hết hạn, chúng không tăng số đếm của chúng.

Kết luận ở đây: với các tác vụ dài, ThreadPool sẽ thực hiện một số tác vụ chờ phía sau những người khác! Vì vậy, tôi thực sự khuyên bạn không nên thực hiện bất kỳ xử lý lâu dài nào trong các tác vụ ThreadPool (chẳng hạn như các trình xử lý hoàn thành không đồng bộ). Nếu không, bạn có thể giữ các cuộc gọi không đồng bộ quan trọng hơn hoàn tất nếu xử lý dữ liệu của bạn đang hoán đổi CPU hoặc bạn có thể có hiệu năng rất không ổn định nếu chỉ một số tác vụ thực hiện nhiều thao tác.

Sử dụng thực hiện ThreadPool tùy chỉnh từ bài viết

 
T0 = 7175934 
T1 = 6983639 
T2 = 5306292 
T3 = 5078502 
T4 = 3279956 
T5 = 8116320 
T6 = 3262403 
T7 = 7678457 
T8 = 8946761 
T9 = 8500619 
Total = 64328883 
+1

Những gì bạn đã bỏ lỡ từ kết quả của bạn là phiên bản ThreadPool thực hiện tốt hơn đáng kể so với phiên bản không phải của bạn với khoảng 50%! Bài viết đã nói rằng việc sử dụng ThreadPool chậm hơn đáng kể nhưng đó không phải là trường hợp nữa. Như với tất cả mọi thứ trong lập trình mặc dù nó đi xuống để "nó phụ thuộc". Nếu nhiệm vụ của bạn không cần phải bắt đầu thực hiện ngay lập tức thì bạn có thể sử dụng ThreadPool và chúng sẽ kết thúc nhanh hơn do ít chuyển ngữ cảnh hơn, nếu không bạn có thể tự quản lý nó. –

+0

@Matthew: Có, tôi đồng ý rằng ThreadPool tính nhiều hơn ở đây nhưng tôi không đồng ý về lý do. Lý do ThreadPool đếm nhiều hơn là bốn luồng ThreadPool đã tồn tại, trong khi với các luồng mới được tạo thủ công, phải mất một lượng thời gian đáng kể cho luồng thực sự bắt đầu. Vì vậy, tôi sẽ đảo ngược kết luận của bạn: nếu nhiệm vụ của bạn không cần thực thi ngay lập tức, hãy sử dụng một Chủ đề mới; nếu bạn cần thực thi ngay lập tức, hãy sử dụng ThreadPool (và đừng hog nó với các nhiệm vụ dài). – Sander

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