PCCar.ru - Ваш автомобильный компьютер

PCCar.ru - Ваш автомобильный компьютер (http://pccar.ru/index.php)
-   Разработка программ (http://pccar.ru/forumdisplay.php?f=27)
-   -   Нужна небольшая помощь с кодом (.NET, Win) - не могу сообразить (http://pccar.ru/showthread.php?t=19419)

e-statik 25.07.2013 14:33

Нужна небольшая помощь с кодом (.NET, Win) - не могу сообразить
 
Пишу обработчик CAN шины под винду, в Visual Studio, C#.
Раньше под винду и потоки не писал ничего, пытаюсь разобраться, было много опыта только с ASP.NET, сижу буксую... (

Цель - слушать порт 64888.
Для этого худо бедно осилил запуск потока и чтение в нем сообщений через UdpClient - данные получаю и обрабатываю. Но не могу правильно тормознуть чтение, поставить на паузу. Либо целиком выключить созданный поток и соединение в нём.

Пересмотрел много код снипетов, но пока что-то не заработало, делаю явно неправильно.

Помогите пож! Конкретно хочу мочь ставить чтение на паузу, а так же мочь вообще корректно выключить прослушивание порта и корректно завершить поток.

Ниже код, который удалось наваять.

Код в форме:
Код:

// Это срабатывает, когда в радиобатоне выбирается "Слушать/не слушать"
if (thisRadioButton.Checked) // Начать прослушивание
{
        MainWorker = new UdpWorker();
        MainWorker.handlerMessageReceived = ReceiverMessage; // привязал метод, кот. будет дергаться в форме на каждом сообщении

        MainThreadDelegate = new ThreadStart(MainWorker.DoWork);
        MainThread = new Thread(MainThreadDelegate);
        MainThread.Start();
}
else // Остановить прослушивание
{
        MainWorker.RequestStop();
}


Код собственно чтения - полуфабрикат, ищу правильное решение:
Код:

public class UdpWorker
{
        private const int listenPort = 64888;
        private UdpClient listener;

        private volatile bool _shouldStop;

        public delegate void MessageReceived(CanRxMsg msg);
        public MessageReceived handlerMessageReceived;

        public void DoWork()
        {
                listener = new UdpClient(listenPort);
                IPEndPoint groupEP = new IPEndPoint(IPAddress.Loopback, listenPort);

                try
                {
                        while (!_shouldStop)
                        {
                                byte[] bytes = listener.Receive(ref groupEP);
                                if (bytes == null || bytes.Length == 0)
                                        break;

                                dataHandler(bytes); // Этот метод уже выдаст сообщение наружу, его код не привожу, к проблеме мало относится
                        }
                }
                catch (ThreadAbortException)
                {

                }
                finally
                {
                        //listener.Client.Disconnect(false);
                        //listener.Client.Shutdown(SocketShutdown.Both);
                        //listener.Client.Dispose();
                        //listener.Close();
                }
        }

        public void RequestStop()
        {
                listener.Client.Shutdown(SocketShutdown.Receive);
                listener.Client.Close();
                _shouldStop = true;
        }
}


e-statik 25.07.2013 14:38

Сейчас добрался до того, что на десктопе конкретно запинается на
byte[] bytes = listener.Receive(ref groupEP);

Т.е. фактически ничего по порту не проходит, он ждёт. В принципе, всё правильно. Но как его корректно снаружи пнуть, чтобы он перестал слушать - не могу сообразить.

Пытался дёрнуть что-то вроде
listener.Client.Disconnect
или
listener.Client.Shutdown
получаю ошибки, что-то не то делаю...

e-statik 25.07.2013 23:38

Программистов нет совсем? (((

Илия 26.07.2013 12:31

Цитата:

Сообщение от e-statik (Сообщение 265193)
Помогите пож! Конкретно хочу мочь ставить чтение на паузу, а так же мочь вообще корректно выключить прослушивание порта и корректно завершить поток.

http://msdn.microsoft.com/en-us/library/tttdef8x.aspx
Пишут:

Calling Thread.Sleep with Timeout.Infinite causes a thread to sleep until it is interrupted by another thread that calls Thread.Interrupt, or until it is terminated by Thread.Abort.

e-statik 26.07.2013 12:49

Наверное, можно было бы тогда вообще вызывать Thread.Abort.
И создавать новый, когда снова надо слушать порт.

Но я попробовал - вызывал Thread.Abort, а потом заново попытался создать. Эксепшн: ругается на уже открытое соединение по этому порту. Явно зависает на listener.Receive.
Где-то проскакивало, что лучше использовать не устаревший Receive, а BeginReceive и EndReceive (или как-то так).

e-statik 26.07.2013 12:51

Короче, похоже, что разбираться нужно скорее не с потоками, а с UdpClient и правильной работой с ним. Так, видимо...
Ну или всё же надо как-то корректно вырубить поток, чтобы он сам отключил соединения и всё остальное, что успел запустить инстанс UdpClient. И тупой Thread.Abort этого явно не делает.

Илия 26.07.2013 12:52

закрывай слушателя и чисти ресурсы. Сначала Close потом Dispose.

Илия 26.07.2013 12:54

Цитата:

Сообщение от e-statik (Сообщение 265267)
надо как-то корректно вырубить поток, чтобы он сам отключил соединения и всё остальное

Он этого делать за тебя не будет! :big:

e-statik 26.07.2013 12:57

О... заработало что ли

Сделал так:
MainWorker.RequestStop();
MainThread.Abort();

а в RequestStop:
listener.Client.Close();
listener.Client.Dispose();
_shouldStop = true;

И стало нормально запускаться и глушиться.

Спасибо!

Илия 26.07.2013 13:02

Рад помочь!


Часовой пояс GMT +4, время: 03:21.

Работает на vBulletin® версия 3.8.4.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot