2009-12-03 34 views
33

Tôi cần thực hiện 3 tác vụ song song và sau khi hoàn thành mỗi tác vụ, họ nên gọi cùng một chức năng để in ra kết quả.Các đại biểu không đồng bộ Vs Thread/ThreadPool?

Tôi không hiểu trong .net lý do tại sao chúng tôi có cuộc gọi không đồng bộ (delegate.BeginInvoke() & delegate.EndInvoke()) cũng như lớp Thread?

Tôi hơi bối rối khi sử dụng khi nào? Bây giờ trong trường hợp cụ thể này, tôi nên sử dụng Asychronous calling hoặc Thread class?

Tôi đang sử dụng C#.

Trả lời

44

1. Asynchronous đại biểu

gọi không đồng bộ được sử dụng khi bạn có hạng mục công trình phải được xử lý trong nền và bạn quan tâm khi họ kết thúc .

BackgroundWorker vs background Thread

2. BackgroundWorker

  • Sử dụng BackgroundWorker nếu bạn có một nhiệm vụ duy nhất chạy trong nhu cầu nền và để tương tác với UI. và sử dụng nó nếu bạn không quan tâm khi họ hoàn thành công việc của họ. Nhiệm vụ của dữ liệu marshalling và các cuộc gọi phương thức đến chuỗi giao diện người dùng là được xử lý tự động thông qua mô hình dựa trên sự kiện .
  • Tránh BackgroundWorker if (1) lắp ráp của bạn không đã tham khảo lắp ráp System.Windows.Form , (2), bạn cần thread để là một thread foreground, hoặc (3) bạn cần phải thao tác chủ đề ưu tiên.

3. ThreadPool

  • Sử dụng một ThreadPool thread khi hiệu quả là mong muốn.Các ThreadPool giúp tránh các chi phí liên quan với việc tạo, bắt đầu và dừng chủ đề.
  • Tránh sử dụng ThreadPool if (1) nhiệm vụ chạy cho các đời của ứng dụng của bạn, (2), bạn cần thread trở thành một chủ đề foreground, (3), bạn cần phải thao tác các ưu tiên thread , hoặc (4) bạn cần chủ đề để có một bản sắc cố định (hủy bỏ, đình chỉ, khám phá).

4. lớp Thread

  • Sử dụng lớp Thread cho các nhiệm vụ lâu dài và khi bạn đòi hỏi tính năng được cung cấp bởi một mô hình luồng chính thức, ví dụ, chọn giữa nền trước và nền chủ đề, chỉnh ưu tiên luồng, kiểm soát chi tiết hơn t hread thực hiện vv
+2

Một trường hợp khác để sử dụng lớp chuỗi (# 4) thay vì bất kỳ thay thế dựa trên luồng nào (# 1- # 3): Nếu bạn sử dụng bất kỳ lớp nào lưu trữ tham chiếu đối tượng trong trường tĩnh-tĩnh, mục tiêu trực tiếp hoặc gián tiếp của những tài liệu tham khảo đó sẽ không đủ điều kiện để thu thập rác trừ khi hoặc cho đến khi tài liệu tham khảo bị xóa hoặc luồng chứa chúng thoát. Nếu các tham chiếu luồng-tĩnh được lưu trữ trên một luồng thread-pool, có thể chúng sẽ tồn tại ở đó vô thời hạn, có thể tạo ra một rò rỉ bộ nhớ lớn. – supercat

+2

Điều này có vẻ là câu trả lời tốt nhất, tuy nhiên nó là một chút liên quan đến việc không ai đề cập đến bão hòa ThreadPool hoặc gợi ý rằng thời gian để chạy đại biểu ảnh hưởng đến quyết định của bạn. ThreadPool/TaskPool là để nhanh chóng hoàn thành công việc trên một chủ đề nền, nhưng nên giới hạn trong công việc mất ít hơn 50-150ms. Đưa công việc nặng (tức là dài hơn 150ms) có thể dẫn đến độ bão hòa hồ bơi thread và sau đó bạn có thể nhận được sự chậm trễ khó chịu 500ms trong khi thứ ThreadPool thay đổi kích thước. –

0

Nếu bạn có quy trình chạy dài (ví dụ: ứng dụng biểu mẫu, IIS, Dịch vụ web, Dịch vụ Windows), bạn có thể sẽ sử dụng các phương pháp Async tốt hơn. Chủ đề yêu cầu tài nguyên hệ thống và chi phí. Tôi luôn cố gắng tránh tạo chủ đề. Nếu tôi không thể, tôi cố gắng dựa vào ThreadPool để xử lý/quản lý chúng.

Bạn có thể nhận được nhiều thông tin áp dụng hơn nếu bạn có thể cho chúng tôi biết đơn đăng ký của bạn là gì.

BeginInvoke sử dụng đại biểu phía sau hậu trường, nơi mà các phương pháp Async thường không làm.

0

Delegate.BeginInvoke lấy chủ đề threadpool và thực thi đại biểu được truyền trên chuỗi đó. Vì vậy, khi bạn sử dụng BeginInvoke .NET Framework thực hiện rất nhiều công việc như tạo chủ đề mới, bắt đầu từ đó, v.v.

Bạn cũng có thể xem ThreadPool.QueueUserWorkItem (delegate {/ * do stuff * /}); cho một cách tiếp cận thay thế cho các cuộc gọi không đồng bộ.

5

Phương pháp async cơ bản tóm tắt cách công việc thực sự đang được xử lý. Nó có thể được sinh ra trong một quy trình mới, nó có thể được thực hiện trong một chủ đề riêng biệt ... Nó không quan trọng.

Tất cả những vấn đề là bạn đang nói:

  1. Run mã này khi bạn bắt đầu.
  2. Và chạy mã này khi bạn hoàn tất.

Nếu được chọn, tôi sẽ sử dụng phương pháp không đồng bộ hóa API để triển khai cơ chế luồng của riêng mình mọi lúc. Các nhà phát triển khuôn khổ đã làm công việc khó khăn cho bạn, tại sao lại phát minh ra bánh xe.

1

Các đại biểu không đồng bộ được thực hiện bằng cách sử dụng một chuỗi từ nhóm chủ đề. Điều này làm giảm chi phí tạo thủ công một chuỗi và xử lý nó. Threadpool chủ đề có chi phí thấp hơn so với những người mà bạn tạo bằng tay và phải được xử lý.

Ngoài ra, thực hiện một phương pháp trong một thread được tạo thủ mang đến cho bạn nhiều kiểm soát như khả năng làm gián đoạn sợi, hủy bỏ nó, kiểm tra trạng thái của nó, thiết lập ưu tiên của nó vv

đại biểu

Async được sử dụng nếu bạn muốn để nhanh chóng thực hiện một phương thức thực thi không đồng bộ.

Ngoài ra, EndInvoke cho phép bạn trả về một đối tượng cho phép bạn truy xuất kết quả thực hiện. Một Thread.Join, mặc dù chức năng tương đương, không cho phép bạn trả lại bất cứ điều gì.

12

Tôi không hiểu trong .net lý do tại sao chúng tôi có cuộc gọi không đồng bộ (đại biểu.BeginInvoke() & delegate.EndInvoke()) cũng như lớp Thread?

  • gọi không đồng bộ được sử dụng khi bạn có hạng mục công trình phải được xử lý ở chế độ nền và bạn quan tâm khi họ kết thúc.

  • Nhóm chủ đề là khi bạn có các mục công việc cần được xử lý trong nền và bạn không quan tâm khi chúng hoàn thành.

  • Chủ đề dành cho công việc không bao giờ kết thúc.

Ví dụ:

Nếu bạn đang đọc một tập tin lớn từ đĩa và không muốn chặn thread GUI, sử dụng một cuộc gọi async.

Nếu bạn đang lười biếng viết một hoặc nhiều tệp trong nền, hãy sử dụng nhóm chủ đề.

Nếu bạn đang bỏ phiếu hệ thống tệp cứ vài giây để tìm nội dung thay đổi, hãy sử dụng một chuỗi.

+1

Điều này thực sự là khá sai. – FlySwat

+0

Để xây dựng, có được xây dựng trong các lớp học cho hầu hết các ví dụ trong. NET mà xử lý này mà không cần phải sử dụng một threadpool bằng tay. – FlySwat

+0

Tôi không thấy cách gọi QueueUserWorkItem là bất kỳ "thủ công" hơn gọi BeginInvoke. –

3

Tôi không hiểu tại .net lý do tại sao chúng tôi đã asychronous gọi (delegate.BeginInvoke() & delegate.EndInvoke()) cũng như Chủ đề lớp học?

Nói chung lý do tại sao - ngay cả trong một hệ thống được thiết kế tốt - luôn có nhiều cách để làm một điều, là vì một số thứ là cơ sở cao cấp được xây dựng từ những cơ sở cấp thấp. Nếu có một cơ sở cấp cao phù hợp với nhu cầu của bạn, đó là ngày may mắn của bạn. Nếu không, bạn phải tự xây dựng nó bằng cách sử dụng các cơ sở cấp thấp.

Lớp Thread sử dụng Win32's BeginThread, vì vậy bạn không phải làm như vậy. Hồ bơi chủ đề sử dụng lớp học Thread, do đó bạn không phải làm như vậy. BeginInvoke sử dụng nhóm chủ đề, do đó bạn không phải làm như vậy, v.v.

1

Đây là một chuỗi dài bị lãng quên, nhưng một cái gì đó mà không được đề cập ở đây là có hai loại công việc, tính toán và I/O bị ràng buộc.

Trong trường hợp công việc tính toán, điều này được thực hiện trong một chuỗi riêng biệt (nếu bạn sử dụng mẫu BackgroundWorker hoặc Begin/End, điều này đến từ nhóm Chủ đề; hoặc, một chuỗi tùy chỉnh nếu bạn quyết định tạo chuỗi của riêng mình).

Mặt khác, cổng I/O được thực hiện trong các cổng I/O (hỗ trợ phần cứng) và không yêu cầu một luồng; Truy cập tệp và Ổ cắm mạng là hai ví dụ về các nhiệm vụ liên kết I/O.

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