ZeroMQ Kill Thread nie działa

Odpowiedz Nowy wątek
2014-06-20 14:38
0

Siemka
Tworzę projekt z użyciem ZeroMQ i mam taki problem. Potrzebuję funkcji do startowania i ubijania dodatkowego wątku. Jak Start działa ok tak ze stopem są problemy. Poniżej kod:

 
private Thread _workerThread;
private object _locker = new object();
private bool _stop = false;
 
public void Start()
        {
            _workerThread = new Thread(RunZeroMqServer);
            _workerThread.Start();
        }
 
public void Stop()
        {
            lock (_locker)
            {
                _stop = true;
            }
 
            _workerThread.Join();
            Console.WriteLine(_workerThread.ThreadState);
        }
 

Gdzieś w internecie znalazłem też coś takiego:

 
void AsyncZmqListener::Stop()
{
    _stopped = true;
    delete _zmqContext;             // <-- Crashes the application. Changing to 'zmq_term(_zmqContext)' does not terminate recv()
    pthread_join(_thread, NULL);    // <-- This waits forever
}
 

ale właśnie tak jak jest napisane w komentarzach, nie działa to.

Ma ktoś może jakiś pomysł na tą funkcję stopa?

Pozostało 580 znaków

2014-06-20 17:58
0

Mógłbyś pokazać metodę RunZeroMqServer?


szogun

Pozostało 580 znaków

2014-06-20 18:39
0

Jasne

 
private void RunZeroMqServer()
        {
            using (var context = ZmqContext.Create())
            using (ZmqSocket server = context.CreateSocket(SocketType.REP))
            {
                /*
                var bindingAddress = new StringBuilder("tcp://");
                bindingAddress.Append(_ipAddress);
                bindingAddress.Append(":");
                bindingAddress.Append(_port);
                server.Bind(bindingAddress.ToString());
                */
 
                //server.Bind("tcp://192.168.0.102:50000");
                server.Bind("tcp://*:12345");
 
                while (!_stop)
                {
                    string message = server.Receive(Encoding.Unicode);
                    if (message == null) continue;
 
                    var response = ProcessMessage(message);
                    server.Send(response, Encoding.Unicode);
 
                    Thread.Sleep(100);
                }
            }
        }
 
private string ProcessMessage(string message)
        {
            ServiceRepositoryMessage srm = JsonConvert.DeserializeObject<ServiceRepositoryMessage>(message);
            string response = "";
 
            switch (srm.FunctionName)
            {
                case "registerService":
                    registerService(srm.ServiceName, srm.ServiceAddress, srm.BindingType);
                    return response = srm.ServiceName + " on " + srm.ServiceAddress + " using a " + srm.BindingType + " protocol was registered!";
                case "unregisterService":
                    unregisterService(srm.ServiceName);
                    return response = srm.ServiceName + " was unregistered";
                case "getServiceAddress":
                    return response = getServiceAddress(srm.ServiceName, srm.BindingType);
                case "isAlive":
                    isAlive(srm.ServiceName);
                    return response = srm.ServiceName + " is alive and kicking!";
                default:
                    return response = "Wrong service name, the only acceptable names are: registerService, unregisterService, getServiceAddress, isAlive";
            }
        }
 

Funkcje registerService itp. to są już funkcję operujące na bazach danych, dodające do bazy adres serwisu który się połączy z moim itd

Pozostało 580 znaków

2014-06-20 19:11
0

Na początek pole _stop to że odwołujesz się do tej samej zmiennej nie znaczy że odwołujesz się do tego samego obszaru pamięci procesory i kompilatory robią wiele optymalizacji.
Poczytaj o Thread.MemoryBarrier i volatile


szogun

Pozostało 580 znaków

2014-06-23 13:38
0

zamiast

Thread 

używaj <code class="csharp">Task 

( zalecane przez M$ ). Klasa Task jako jeden z parametrów konstruktora przyjmuje CancelationTokenSource. Ustawiasz ten token na .cancel a w tasku w bloku Try/Catch sprawdzasz status tego tokena i w momencie gdy token ustawi się na ThrowIfCancelationRequested ( piszę z pamięci więc mogę pomylić się w nazewnictwie ) rzucany jest wyjątek a ty po prostu w Finally obsługujesz go i kończysz Task. Sprawdź czy konstruktor Task przyjmuje ten token. Jest on raczej używany do "odpal i zapomnij". Natomiast <code class="csharp">Task<T>


 na pewno jako jeden z parametrów przyjmuje token.

Możesz też użyć Backgroundworker który bazuje na Task/Thread i sam z siebie wspiera zatrzymanie pracy z podaniem wyniku tej pracy.
edytowany 1x, ostatnio: wedlock, 2014-06-23 13:40

Pozostało 580 znaków

2014-06-23 18:09
0

Akurat w tym przypadku wątek może okazać się lepszym rozwiązaniem od Taska. Task jest przeznaczony dla zadań które trwają kilka do kilkudziesięciu sekund w ten sposób wątek jest zwracany do puli wątków i może zostać wykorzystany ponownie. Jeżeli metoda wywoływana w Tasku będzie trwała wiele minut albo godzin, a w międzyczasie inne elementy kodu będą uruchamiać inne zadania może się okazać, że pula wątków za bardzo się rozrośnie (zwłaszcza gdy takich dużych zadań będzie kilka). A CancelationTokenSource działa też na wątkach.


szogun

Pozostało 580 znaków

2014-06-24 08:12
0

Pozwolę sobie nie zgodzić się z tobą.

szogun1987 napisał(a):

Akurat w tym przypadku wątek może okazać się lepszym rozwiązaniem od Taska. Task jest przeznaczony dla zadań które trwają kilka do kilkudziesięciu sekund w ten sposób wątek jest zwracany do puli wątków i może zostać wykorzystany ponownie.

A skąd ta wiedza. Ja czytając o Taskach wyczytałem jedynie, że jest to następca klasy Thread i korzystanie z tego ma zapewnić kompatybilność dla programu w przyszłości po wycofaniu klasy Thread. Zresztą pod skórą Task-a i tak siedzą niektóre metody i mechanizmy z Thread-a. Nigdzie nie czytałem o takim podziale tych klas.

szogun1987 napisał(a):

Jeżeli metoda wywoływana w Tasku będzie trwała wiele minut albo godzin, a w międzyczasie inne elementy kodu będą uruchamiać inne zadania może się okazać, że pula wątków za bardzo się rozrośnie (zwłaszcza gdy takich dużych zadań będzie kilka).

Jeśli przekroczysz pulę wątków to i Taski się zblokują . Natomiast zadania będą wykonywane w kolejce bo czekają na swoją kolej w sposób podobny do SpinWait. Oczywiście czas wykonania będzie olbżymi ale .... jak chciał programista tak ma.

Skoro Task ma wykonywać się długo to przy tworzeniu proszę podać mu Schedulera z parametrem LongRunningTask.

Pozostało 580 znaków

2014-06-24 12:44
0
wedlock napisał(a):

Ja czytając o Taskach wyczytałem jedynie, że jest to następca klasy Thread i korzystanie z tego ma zapewnić kompatybilność dla programu w przyszłości po wycofaniu klasy Thread. Zresztą pod skórą Task-a i tak siedzą niektóre metody i mechanizmy z Thread-a. Nigdzie nie czytałem o takim podziale tych klas.

A gdzie to przeczytałeś?
Task to właściwie takie opakowanie na ThreadPool, trudno to nazwać następcą Thread, bo cel trochę inny. Wycofanie klasy Thread?! Kto, kiedy i po co miałby to robić?


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2014-06-24 14:03
0

a tu : http://helion.pl/ksiazki/prog[...]ki-rafal-pawlaszek,proch5.htm

autorzy książki sugerują, że Task jest "następcą" Thread bo nowinki języka 4.5 zmierzają do większego zastosowania async/await tak aby kod był przejrzysty tak jak by napisany synchronicznie. Sugerują tym, że taka jest polityka M$ i w tym kierunku zmierza język C#.

edytowany 1x, ostatnio: wedlock, 2014-06-24 14:11
Ok, przynajmniej wiadomo, do jakiej książki nie warto zaglądać. - somekind 2014-06-24 14:20
A to nie bylo przypadkiem, ze jest nastepca w kontekscie "Odpal i kiedys wroc"? Podaj strone. - n0name_l 2014-06-24 21:29

Pozostało 580 znaków

2014-06-24 21:19
1

Klasa Task jest lepszym rozwiązaniem w przypadku gdy zadanie ma nie blokować interfejsu użytkownika albo jak w przypadku asynchronicznych akcji w kontrolerze ma za zadanie odciążyć pulę wątków zajmującą się przetwarzaniem wywołań. Możliwość korzystania z async i await też przemawia za tym żeby myśleć o Task'u zanim się pomyśli o wątku. Klasy Thread podobno nie ma w aplikacjach Windows Store (nie pisałem tych aplikacji więc nie wiem), ale z .Net jako takiego nie zostanie wyrzucona z wielu względów. Głównie przez wsteczną kompatybilność oraz fakt że zachowanie puli wątków nie zawsze jest zgodne z intencjami programistów - tych zaawansowanych.
Co do rozrostu puli wątków to z tego co pamiętam (ale mogę się mylić) jedna z jej implementacji podwaja ilość wątków gdy te się wyczerpią, respektując przy tym tylko metodę ThreadPool.SetMaxThreads.


szogun
zachowanie puli wątków nie zawsze jest zgodne z intencjami programistów - tych zaawansowanych., co ma tu zaawansowanie do rzeczy? O.o - n0name_l 2014-06-24 21:27
Chodzi mi o to że początkujący nie koniecznie potrafią ubrać swoje intencje w słowa a tym bardziej w kod i w ich przypadku nawet gdy pula wątków nie jest najwydajniejsza, albo zanieczyszcza kod bardziej niż wątki to i tak powinni z niej skorzystać. - szogun1987 2014-06-24 21:42

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0