Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопрос по многопоточке 
:(
    Опции темы
ДобренькийПапаша
Дата 17.5.2011, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: нет
Всего: 7



Код

static void Main(string[] args)
        {
            CardDispenser dispenser = new CardDispenser("COM4", 9600, Parity.None, 8, StopBits.One);
            
            dispenser.Send(dispenser.Command["DC"]);
            
            Thread.Sleep(5000); //Без этой строки следующий посыл команды выполняется раньше времени

            dispenser.Send(dispenser.Command["CP"]);

            dispenser.Close();
            Console.ReadLine();
        }       


Код

//в функции Send посыл данных на com-порт
this.Write(batch.BatchByteSequence.ToArray(), 0, batch.BatchByteSequence.Count);


Код

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            string response = this.ReadExisting();
            byte[] byteResponse = Encoding.GetBytes(response);
            int answerCode = byteResponse[0];
            if (answerCode == 6)
            {
                Send(Command["ENQ"]);
            }
        }


Нужно, чтобы Handler отработал и вообще всё сначала отработало, а только потом выполнялась следующая команда. Sleep() вызывать не дело. А с многопоточкой я почти не работал. Как лучше здесь поступить?


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
-Mikle-
Дата 17.5.2011, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 17
Всего: 59



Вот блокирующий (синхронный) вариант:

Код

........................
AutoResetEvent waitHandle = new AutoResetEvent(false);

bool Send(........, int timeout)
{
  ...........
  return waitHandle.Wait(timeout);
}

void DataReceivedHandler(..........)
{
   .............
   waitHandle.Set();
}


Это не многопоточный и самый самый простой вариант. Send можно вызывать только из одного одновременно.
Подходит?

Добавлено через 3 минуты и 40 секунд
Можно еще делать очередь и обрабатывать очередь по завершению предыдущей команды.


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
ДобренькийПапаша
Дата 18.5.2011, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: нет
Всего: 7



Я переформулирую проблему топика. Код я неправильный привёл. Проблема такая:

Метод Send отправляет на порт пакет данных (команду) и возвращает ответ (тоже пакет данных - класс Batch). DataReceived-событие возбуждается системой, когда ей в голову придёт (пока там команда дойдёт до порта и устройство начнёт отвечать). Ожидание ответа (срабатывание события) сейчас мной сделано через цикл while как видно в методе ReceiveResponseBatch(). Вообще говоря, это работает. Но как-то это извращённо и некрасиво. Как можно сделать красиво?
Код

private bool IsAnswerReceived=false;

        //Получение данных       
        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            IsAnswerReceived = true;
        }

        //Отправление данных
        public override Batch Send(CommandAttributes attributes)
        {
            Batch batch = new Batch(attributes.CommandName);
            SendBatch(batch);

            return ReceiveResponseBatch();
        }

        //Получение данных
        private Batch ReceiveResponseBatch()
        {
            int waitingIntervals = 0;
            while(!IsAnswerReceived)
            {
                waitingIntervals++;
                if (waitingIntervals > 50) break;
                Thread.Sleep(200);
            }

            if (IsAnswerReceived)
            {
                string response = this.ReadExisting();
                byte[] byteResponse = Encoding.GetBytes(response);
                
                IsAnswerReceived = false;

                return new Batch(byteResponse);
            }            
            return null;
        }


А как очередь организовать? Что ты здесь имел ввиду конкретно?

Это сообщение отредактировал(а) ДобренькийПапаша - 18.5.2011, 20:52


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
neic
Дата 19.5.2011, 00:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 839
Регистрация: 28.1.2007

Репутация: 1
Всего: 7



Может стоит использовать Semaphore? и очередь автоматически формируется и управлять легче всем эти делом будет.
PM MAIL WWW ICQ Skype   Вверх
-Mikle-
Дата 19.5.2011, 07:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 17
Всего: 59



Я приводил код выше. Если смотреть по аналогии с вашим, то waitHandle - это как бы флаг IsAnswerReceived.
То есть:
Код

        private AutoResetEvent waitHandle = new AutoResetEvent(false);

        //Получение данных       
        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            waitHandle.Set();
        }

        //Отправление данных
        public override Batch Send(CommandAttributes attributes, int timeout = 10000)
        {
            Batch batch = new Batch(attributes.CommandName);
            SendBatch(batch);
            return (waitHandle.Wait(timeout)) ? ReceiveResponseBatch() : null;
        }

        //Получение данных
        private Batch ReceiveResponseBatch()
        {
            string response = this.ReadExisting();
            byte[] byteResponse = Encoding.GetBytes(response);
            return new Batch(byteResponse);
        }


Посмотри еще на Semaphore, как посоветовал neic, его тоже можно прикрутить тут.

А про очередь, я имел ввиду асинхронный вариант. То есть метод Send ничего не возвращает, обработанные ответы передаются событием или делегатом. То есть по обычному асинхронному шаблону. Пример писать щас не хочу, потому что не знаю нужен ли тебе он.


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0446 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.