2009-11-04 30 views
8

Tôi không chắc chiến lược nào sẽ áp dụng ... Tôi đang tập trung vào hoạt động của mình, nhưng tôi cũng muốn giữ các vấn đề về hiệu năng trong một phút. ..có một phương pháp được gọi là Thực hiện() phải chờ (chạy đồng bộ) cho đến khi một thao tác hoàn tất. Thao tác này xảy ra trên một chuỗi khác. Có 2 cách để thực hiện điều tương tự ...Để lựa chọn giữa ManualResetEvent hoặc Thread.Sleep()

Bằng cách sử dụng ManualResetEvent

void Execute() 
{ 
    taskHandle = new ManualResetEvent(false); 
    . 
    . 
    //delegate task to another thread 
    . 
    . 
    taskHandle.WaitOne(); 
} 

HOẶC

Bằng cách sử dụng một cách đơn giản trong khi xây dựng

void Execute() 
{ 
    . 
    . 
    //delegate task to another thread 
    . 
    . 
    while (!JobCompleted) 
     Thread.Sleep(1000); 
} 

Mà một trong hai cách tiếp cận tôi nên áp dụng ... tại sao?

CHỈNH SỬA:

Q2. Điều gì sẽ xảy ra nếu tôi chỉ có một sự tương phản trống rỗng? Có gì khác biệt...?

while(!JobCompleted); 

EDIT: (cái gì tôi thu thập được trước đó)

http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml - Bài viết này nói manualresets là comparitively chậm hơn bởi vì họ đi ra khỏi mã số quản lý và trở lại trong ...

+0

Chỉ muốn chỉ ra Thread.Sleep (0) cách sử dụng. Chỉ định số không (0) để chỉ ra rằng luồng này sẽ bị đình chỉ để cho phép các luồng chờ khác thực thi. Trong trường hợp này, Sleep (0) tốt hơn Sleep (1000), nhưng việc sử dụng WaitHandle vẫn phù hợp hơn. –

+4

Vòng lặp rỗng trong cơ bản là một spinwait- nó sẽ tiêu thụ hoàn toàn một CPU. Không được khuyến khích. – nitzmahone

Trả lời

13

Ngoài sự tò mò, tại sao ManualResetEvent và không phải AutoResetEvent? Dù bằng cách nào, đi với hệ điều hành nguyên thủy trên một phương pháp ngủ-kiểm tra giấc ngủ.

Bạn cũng có thể sử dụng khóa Monitor (hoặc rõ ràng qua Monitor.EnterMonitor.Exit hoặc qua khối lock), nhưng cách tiếp cận phải dựa trên những gì bạn đang thực sự làm; nếu đó là kịch bản "chỉ có một trong số điều này và tôi cần quyền truy cập độc quyền", thì hãy sử dụng khóa Monitor. Nếu đó là "Tôi cần đợi cho đến khi luồng khác kết thúc vì các lý do khác với quyền truy cập tài nguyên", sau đó sử dụng AutoResetEvent hoặc ManualResetEvent.

Những gợi ý để sử dụng Thread.Join là tốt nếu (và chỉ nếu)

  1. Bạn có thể truy cập Thread đối tượng khác
  2. Bạn không muốn thực hiện cho đến khi thread khác chấm dứt.

Nếu không đúng (bạn không có quyền truy cập hoặc chuỗi khác sẽ không chấm dứt, nó sẽ chỉ báo hiệu "tất cả rõ ràng") thì Thread.Join không thể thực hiện được.

Tùy chọn tồi tệ nhất là

while(!JobCompleted);

Như sẽ tie lên bộ vi xử lý với kiểm tra không cần thiết của biến mà không cần bất kỳ tạm dừng ở giữa chúng. Có, nó sẽ chặn chuỗi của bạn cho đến khi thao tác hoàn tất, nhưng bạn sẽ tối đa hóa việc sử dụng CPU (hoặc ít nhất là giá trị của một lõi).

+0

đọc một cách rõ ràng các thiết lập lại thủ công hoạt động ở chế độ hạt nhân ... nếu vậy thì sẽ có chi phí hiệu năng, phải không? PS: Tôi đã chỉnh sửa câu hỏi một lần nữa ... – deostroll

+0

Bạn đề nghị đi với hệ điều hành nguyên thủy, nhưng bạn thực sự cần giải thích tại sao. – Gigi

2

Nếu bạn có quyền truy cập vào đối tượng Thread ban đầu hoặc có thể nhận được quyền truy cập đó, tốt nhất bạn nên sử dụng Thread.Join().

Edit: Ngoài ra, nếu điều này là diễn ra trong một giao diện giống như WinForms hoặc WPF, bạn có thể muốn xem xét sử dụng BackgroundWorker

+0

tôi không truy cập vào đối tượng chuỗi ... – deostroll

+0

Sau đó, sử dụng ManualResetEvent như @nitzmahone đề xuất. Hoặc tìm cách để có được Chủ đề đó. Hạn chế duy nhất với việc sử dụng ManualResetEvent là cả người gọi và nhân viên đều phải sử dụng nó, tạo ra một sự phụ thuộc có thể không mong muốn. – Randolpho

+0

@Randolpho. Cả hai phương pháp đều không phải chia sẻ tài nguyên để có thể báo hiệu lẫn nhau? Trong trường hợp của vòng lặp while, cả hai luồng phải biết về boolean 'JobCompleted'. – rocka

4

Sự kiện này làm cho sử dụng hiệu quả hơn các processors- bạn không cần phải đánh thức chuỗi chủ đề gốc đến cuộc thăm dò ý kiến. Hạt nhân sẽ đánh thức bạn khi sự kiện cháy.

+0

Nhưng các hướng dẫn sử dụng có giá trị cao hơn so với các cấu trúc khác. Tôi sử dụng .net 2.0. Đọc một nơi nào đó tht thủ công reset làm việc trong chế độ hạt nhân, nơi các lựa chọn thay thế màn hình của nó hoạt động ở chế độ người dùng ... để thay đổi quá mức do thay đổi chế độ ...! Điều này có đúng không? – deostroll

+0

Chúng đắt tiền hơn so với Màn hình, nhưng chúng cũng hoàn toàn nổi bật hơn. Nó phụ thuộc vào mức độ thường xuyên bạn tạo ra chúng. Nếu bạn muốn chạy hàng nghìn giây này, cách tiếp cận trọng lượng nhẹ hơn sẽ tốt hơn. – nitzmahone

2

Những bất lợi chính khi sử dụng Thread.Sleep() là bạn đang đưa ra quyết định về thời gian mà chuỗi sẽ chờ. Thao tác bạn đang đợi có thể mất nhiều hơn hoặc ít hơn thời gian và nói chung, rất khó định lượng chính xác thời gian đó. Nếu luồng ngủ quá dài, thì bạn không tận dụng tối đa tài nguyên hệ thống.

Để tối ưu, bạn nên sử dụng ManualResetEvent (hoặc AutoResetEvent) để chuỗi của bạn được tiếp tục ngay sau khi thao tác phụ thuộc hoàn tất.

0

Cả hai cách tiếp cận đều giống nhau về cơ bản. Tuy nhiên, vòng lặp while rõ ràng hơn một chút, vì bạn có thể chỉ định thời gian ngủ. Mặc dù tôi sẽ sử dụng các lớp XXXResetEvent được sử dụng trong kịch bản mà bạn đang làm việc. Tôi cho rằng các lớp luồng sẽ được triển khai ngay bây giờ hoặc sau đó với mã luồng mạnh hơn để xử lý mối quan hệ luồng trên bộ xử lý đa lõi.

+0

Một ManualResetEvent hoạt động khá khác với việc bỏ phiếu định kỳ. –

1

ManualResetEvent chắc chắn là con đường để đi.

Từ đoạn mã bạn đã cung cấp, có vẻ như bạn đang ủy quyền thực thi trong phương thức Thực thi của bạn. Nếu trường hợp này xảy ra, và bạn chỉ ủy thác một nhiệm vụ duy nhất, tại sao bạn lại ủy thác cho một luồng khác nếu bạn phải chờ phản hồi? Bạn cũng có thể thực hiện quá trình một cách đồng bộ.

1

manualresets là comparitively chậm hơn bởi vì họ đi ra khỏi mã số quản lý và trở lại trong ..

Họ có lẽ chậm hơn so với nói một Wait/Pulse combo, mà bạn nên sử dụng ở đây theo ý kiến ​​của tôi. Nhưng Manual/AutoResetEvents sẽ nhanh hơn bất kỳ Thread.Sleep(x) nào mà bạn thực hiện, ngay cả khi bạn chọn x = 1. Và thậm chí nếu bạn hạ thấp độ phân giải bộ đếm thời gian Windows xuống 1ms.

Điều gì xảy ra nếu tôi chỉ có một khoảng trống trong khi tương tác? Có gì khác biệt...?

Sau đó, một lõi sẽ quay ở mức 100% cho đến khi điều kiện trở thành sự thật, đánh cắp thời gian từ các chủ đề khác mà có thể sử dụng nó để thực hiện điều gì đó hữu ích, như tính toán khung cho "Angry Birds". làm mát một chút, trì hoãn hiệu ứng thảm khốc của hâm nóng toàn cầu cho một số nano giây tiếp theo.

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