Strona główna > .NET > Tropem wątków, czyli Thread.Sleep(-1) i tajemnica braku wyników wyszukiwania w Google.

Tropem wątków, czyli Thread.Sleep(-1) i tajemnica braku wyników wyszukiwania w Google.

Wczoraj był dniem kiedy miałem nadzieje, w końcu zakończyć kodowanie jednego z wrapperów na Azure SDK, który miał zarządzać usługami, które aktualnie buduje. Mam taki dziwny zwyczaj, że jak zastępuje czyjś kod (tu: Microsoft) to sprawdzam najpierw jak podeszli do tematu by nie powtórzyć czegoś co mi się nie podobało w poprzedniej implementacji lub/i nauczyć się czegoś ciekawego by dołączyć to do mojej nowej implementacji.

Tak też było i tym razem: znajduję w kodzie jednej z bibliotek taki oto kod:

Thread.Sleep(-1);

hmmm – i to tyle co mogłem wtedy powiedzieć.

Co robi Thread.Sleep to raczej wiadomo – zatrzymuje wykonywanie aktualnego wątku na zadaną liczbę milisekund. Ciekawe jednak było to co oznacza –1 w tym całym zamieszaniu, bo powszechnie wiadomo, że czasu w liczbach ujemnych tu nie liczymy.

Po zdekompilowaniu biblioteki, gdzie jest klasa Thread znajdziemy przy wywołaniu Thread.Sleep coś jeszcze bardziej interesującego:

if (num < -1L || num > (long) int.MaxValue)
        throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));


Co jasno wskazuje, na to, że tylko wartość –1 jest wykluczona z generowania błędu dla wartości ujemnych…czyli to oznacza… że –1 coś oznacza.

Idąc dalej tym tropem dochodzimy do momentu, w którym wiadomo co .NET wywołuje w systemie by zatrzymać wątek – jest to

SleepEx

The SleepEx function causes the current thread to enter a wait state until one of the following occurs:· An I/O completion callback function is called· An asynchronous procedure call (APC) is queued to the thread.· The time-out interval elapses

z kernel32.dll

idąc dalej tropem dokumentacji jest tam napisane, że

A value of INFINITE causes an infinite delay.

a tak całkiem przypadkiem to INFINITE to właśnie stała wynosząca –1.

Thread.Sleep (-1) wyłącza wykonywanie aktualnego wątku i zamraża go w danym momencie na czas “nieokreślony.

Ładnie to widać w tym kawałku kodu

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Jeden");

            var x = new Thread(new ThreadStart(delegate
                {
                    while (true)
                    {
                        Console.WriteLine(Guid.NewGuid());
                    }
                }));

            x.Start();

            Thread.Sleep(-1);

            Console.WriteLine("dwa");

        }
    }

  • Uruchamiamy program i widzimy napis Jeden
  • Później lecą w nieskończoność nowe GUIDy na ekranie z drugiego – nowoutworzonego wątku
  • Napis dwa nie pokazuje się na ekranie, wątek aktualny jest zamrożony i nie ma zamiaru się ruszyć.

 

Ciekawe w tym wszystkim jest to, że niewiele jest w Google o tym –1, a to już wyzwanie, by dzisiaj mieć temat, którego Google nie rozwiązuje na pierwszej stronie wyników wyszukiwania.

Kategorie:.NET Tagi: , ,
  1. witoldbolt
    Lipiec 17, 2013 o 2:13 pm

    Hej.

    Zwróć uwagę na to, że SleepEx zatrzyma wątek do czasu jednego z 3 zdarzeń. Jeśli ustawimy timeout na nieskończoność, to znaczy że chcemy zrezygnować z jednego z tych zdarzeń i czekać albo na „An I/O completion callback function is called” albo „An asynchronous procedure call (APC) is queued to the thread”. Szczególnie to drugie jest ciekawe. Możemy mieć wątek do obsługi wołań asynchronicznych, który sobie śpi i wzbudza się tylko wtedy gdy trzeba.

    A poza tym czytając MSDN bez żadnego debugowania, rozkompilowywania itd.. można znaleźć:
    http://msdn.microsoft.com/en-us/library/d00bd51t.aspx i czytamy:

    millisecondsTimeout
    Type: System.Int32
    The number of milliseconds for which the thread is blocked. Specify zero (0) to indicate that this thread should be suspended to allow other waiting threads to execute. Specify Infinite to block the thread indefinitely.

    I możemy dalej kliknąć na słowo Infinite (http://msdn.microsoft.com/en-us/library/system.threading.timeout.infinite.aspx) żeby zobaczyć opis, w którym widać, że Infinity = -1 🙂

    Wynika z tego, że Thread.Sleep(-1); to BAD PRACTICE. Powinno się pisać Thread.Sleep(Timeout.Infinite); i wtedy wszystko jest jasne 😉

  2. Lipiec 17, 2013 o 8:58 pm

    Witku, faktycznie zachowanie Thread, a tu tak na prawdę SleepEx jest ciekawe i dlatego postanowiłem rzucić rękawice i zaproponować temat- w dużej mierze go wyczerpałeś załączonymi linkami 🙂

  3. mariusz
    Lipiec 23, 2013 o 7:41 am

    Thread.Sleep(Timeout.Infinite);

  1. No trackbacks yet.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d blogerów lubi to: