2009-11-04 9 views
8

Nie jestem pewien, którą strategię zastosować ... Koncentruję się na tym, że moja operacja jest zakończona, ale chciałbym również, aby problemy z wydajnością były minimalne. ... istnieje metoda o nazwie Execute(), która musi czekać (działać synchronicznie) do zakończenia operacji. Ta operacja dzieje się w innym wątku. Istnieją 2 sposoby realizują to samo ...Aby dokonać wyboru między ManualResetEvent lub Thread.Sleep()

Korzystając ManualResetEvent

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

LUB

za pomocą prostego natomiast skonstruować

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

którym jeden z dwóch podejść powinienem przyjąć ... dlaczego?

EDYTOWANIE:

Q2. A co, gdybym po prostu miał puste podczas pracy? Co za różnica...?

while(!JobCompleted); 

EDIT: (coś Zebrałem wcześniej)

http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml - Ten artykuł mówi manualresets są comparitively wolniej, ponieważ wychodzą z kodu zarządzanego i z powrotem w ...

+0

prostu chcę podkreślić Thread.Sleep (0) użytkowania. Określ zero (0), aby wskazać, że ten wątek powinien zostać zawieszony, aby umożliwić wykonanie innych oczekujących wątków. W tym przypadku Sleep (0) jest lepszy niż Sleep (1000), ale używanie WaitHandle jest jeszcze bardziej odpowiednie. –

+4

Pusta pętla while jest w zasadzie wirówką, która całkowicie pochłonie procesor. Niepolecane. – nitzmahone

Odpowiedz

13

Z ciekawości, dlaczego ManualResetEvent, a nie AutoResetEvent? Tak czy siak, idź z prymitywem systemu operacyjnego OS za pomocą trybu "sleep-check-sleep".

Można również użyć blokady Monitor (jawnie przez Monitor.Enter i Monitor.Exit lub poprzez lock bloku), ale podejście powinno być oparte na co jesteś rzeczywiście robi; jeśli jest to scenariusz „jest tylko jedna z tych rzeczyi muszę wyłącznego dostępu”, a następnie użyć blokady Monitor. Jeśli jest to „muszę czekać aż inny wątek zakończy z powodów innych niż dostęp do zasobów”, a następnie użyć AutoResetEvent lub ManualResetEvent.

sugestie używać Thread.Join są dobre, jeśli (i tylko wtedy)

  1. mieć dostęp do innych Thread obiektu
  2. Nie chcesz wykonać aż inny wątek kończy.

Jeśli któraś z nich nie jest prawdziwa (nie masz dostępu, lub drugi wątek się nie zakończy, to po prostu zasygnalizuje "wszystko jasne"), wtedy Thread.Join nie jest opłacalny.

Najgorszym rozwiązaniem jest

while(!JobCompleted);

Jako że zwiąże się procesor z niepotrzebnych kontroli zmiennej bez żadnej przerwy pomiędzy nimi. Tak, zablokuje twój wątek, dopóki operacja nie zostanie zakończona, ale maksymalnie wykorzystasz CPU (lub przynajmniej wartość jednego rdzenia).

+0

przeczytaj trochę instrukcji tht resetuje pracę w trybie jądra ... jeśli tak, to powinno być obciążenie wydajności, prawda? PS: Ponownie zredagowałem pytanie ... – deostroll

+0

Sugerujesz przejście z prymitywem systemu operacyjnego, ale naprawdę powinieneś wyjaśnić dlaczego. – Gigi

2

Jeśli masz dostęp do oryginalny obiekt Thread, lub możesz uzyskać taki dostęp, najlepiej używać Thread.Join().

Edycja: Również, jeśli to ma miejsce w GUI jak WinForms lub WPF, można rozważyć użycie BackgroundWorker

+0

Nie mam dostępu do obiektu wątku ... – deostroll

+0

Następnie użyj ManualResetEvent, jak sugeruje @nitzmahone. Lub znajdź sposób na zdobycie tego wątku. Jedyną wadą korzystania z ManualResetEvent jest to, że zarówno osoba dzwoniąca, jak i pracownik muszą z niego korzystać, tworząc potencjalnie niechcianą zależność. – Randolpho

+0

@Randolpho. Czy obie metody nie muszą udostępniać zasobów, aby móc wzajemnie się zasygnalizować? W przypadku pętli while oba wątki muszą znać wartość logiczną "JobCompleted". – rocka

4

Impreza pozwala na bardziej efektywne wykorzystanie processors- nie masz się obudzić wątek nadrzędny do ankiety. Jądro Cię obudzi, gdy wydarzenie się rozpocznie.

+0

Ale nie są "manualne Remover drogie w porównaniu do innych konstrukcji. Używam .net 2.0. Czytaj gdzieś, ręczne resetowanie działa w trybie jądra, gdzie jego alternatywy działają w trybie użytkownika ... tak więc dodatkowe obciążenie związane ze zmianą trybu ...! Czy to prawda? – deostroll

+0

Są one droższe do tworzenia niż monitory, ale są również bardziej w pełni funkcjonalne. To zależy od tego, jak często je tworzysz. Jeśli chcesz uruchomić te tysiące na sekundę, podejście lżejsze byłoby lepsze. – nitzmahone

2

Główną wadą korzystania z Thread.Sleep() jest decyzja, jak długo wątek będzie czekać. Operacja, na którą czekasz, może trwać bardzo długo, a generalnie bardzo trudno dokładnie określić czas. Jeśli wątek śpi zbyt długo, nie najlepiej wykorzystujesz zasoby systemowe.

Aby być optymalnym, powinieneś użyć ManualResetEvent (lub AutoResetEvent), aby Twój wątek został wznowiony natychmiast po zakończeniu zależnej operacji.

0

Zasadniczo oba podejścia mają to samo znaczenie. Pętla while jest jednak trochę bardziej wyraźna, ponieważ możesz określić czas snu. Chociaż używałbym klas XXXResetEvent, które mają być używane w scenariuszu, w którym pracujesz. Założę się, że klasy wątków zostałyby zaimplementowane teraz lub później z bardziej rozbudowanym kodem gwintowania, aby poradzić sobie z powinowactwem do wątków w procesorach wielordzeniowych.

+0

ManualResetEvent zachowuje się zupełnie inaczej niż okresowe pobieranie. –

1

ManualResetEvent jest zdecydowanie do zrobienia.

Od Fragment kodu podałeś, to wygląda na to delegowanie wykonania w swoim Execute metody. Jeśli tak jest i delegujesz tylko jedno zadanie, dlaczego w ogóle przekazujesz inny wątek, jeśli musisz poczekać na odpowiedź? Równie dobrze możesz po prostu wykonać proces synchronicznie.

1

manualresets są comparitively wolniej, ponieważ wychodzą z kodu zarządzanego iz powrotem ..

Są prawdopodobnie wolniej niż powiedzieć Wait/Pulse combo, którego należy użyć tutaj moim zdaniem. Ale Manual/AutoResetEvents będzie o wiele szybszy niż jakikolwiek inny Thread.Sleep(x), nawet jeśli wybierzesz x = 1. I nawet jeśli obniżysz rozdzielczość timera Windows do 1 ms.

Co, gdybym po prostu miał puste podczas pracy? Co za różnica...?

Wtedy jeden rdzeń będzie spin na 100%, aż stan okazuje prawdziwe, kradzież z dala czas od innych wątków, które mogłyby zamiast użyć go do zrobienia czegoś pożytecznego, jak obliczania klatek dla „Angry Birds” - czy procesor może po prostu ochłodzić się nieco, opóźniając tragiczne skutki globalnego ocieplenia o kolejne nanosekundy.

Powiązane problemy