![]() |
|
Модераторы: Partizan, gambit |
![]()
|
|
| WantToProg |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 88 Регистрация: 13.4.2009 Репутация: нет Всего: нет |
Доброе время суток. Извиняюсь что так написал название темы, но суть оно отражает. А проблема в следующем:
Я пишу код, который в одном потоке считывает данные из файла и передает их в последовательный порт компьютера. Второй поток возникает по событию DataReceived. Так вот проблема возникла в связи с тем, что мне необходимо закрывать порт по окончании приема данных, и открывать его снова, при отправке. Но вероятно по причине параллельности выполнения потоков, порт не успевает закрываться. Но если проверяю проверяю с точками останова, ошибки не возникает. Подскажите пожалуйста каким образом можно избежать данной ошибки. Насколько я понимаю, необходимо сделать так, что бы первый поток не выполнялся пока не завершится поток по событию DataReceived, но как это сделать, я не знаю. Проблемный код предоставляю ниже:
PS: Причина, по которой порт необходимо закрывать по окончании приема данных, заключается в том, что в файле, который я читаю в начале порты могут быть разные (образец строки из файла 1!2380!23d8!COM3!1!0003!), а считывать и получать данные от устройств мне необходимо последовательно. PPS: Я не программист, так что сильно не ругайте за код, просто приходится параллельно выполнять еще и такие задачи. Прислушаюсь к хорошим советам по улучшению кода. Это сообщение отредактировал(а) WantToProg - 15.2.2010, 11:58 |
|||
|
||||
| Экскалупатор |
|
||||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1746 Регистрация: 1.4.2009 Где: г. Минск Репутация: 11 Всего: 24 |
во-первых, надо закрывать порт не в if, а просто в конце кода. т.е. закрывать в любом случае.
во-вторых, попробуй использовать блок
оберни в него блок кода который работает с портом. должно получиться как то так:
в таком случае все манипуляции с закрытием и ожиданием должны отпасть. по поводу организации кода говорить надо много и долго. по сути тут надо переделывать все. возьми книжку: Стив Макконел "Совершенный код". Мартин Фаулер "Рефакторинг". |
||||||
|
|||||||
| WantToProg |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 88 Регистрация: 13.4.2009 Репутация: нет Всего: нет |
Но в таком случае порт на момент получения данных будет уже закрыт. И с блоком using не все так хорошо. Порт открывается, и тут же закрывается, не получив данные. Возможно я не очень хорошо разбираюсь с даным блоком, но как его использовать в моем коде, я к сожалению не понимаю. Может быть есть аналог WinAPI в C#: EnterCriticalSection, LeaveCriticalSection, WaitForSingleObject? |
|||
|
||||
| Экскалупатор |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1746 Регистрация: 1.4.2009 Где: г. Минск Репутация: 11 Всего: 24 |
значит в таком случае у тебя ошибка в организации всего процесса. как то странно все работает. такое ощущение что сначала слушается порт, а потом открывается новый и при следующем цикле используется старый открытый порт. |
|||
|
||||
| WantToProg |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 88 Регистрация: 13.4.2009 Репутация: нет Всего: нет |
тут наверно я что то не понимаю. Весь код предоставлен выше, ничего другого нет. Если я выполняю дебагинг то получаю следующее: 1. Запускается цикл, в котором получаем необходимые значения для отправки в порт 2. Создается экземпляр порта с необходимыми параметрами 3. Порт открывается 4. Выполняется функция отправки данных 5. Возвращается на место вызова функции 6. Порт закрывается //Вы советовали 7. Параллельно запускается прием данных с порта по событию 8. Данные не могут быть получены и мы получаем Exception IsClosed Прошу, объясните поподробнее, что должно было произойти по вашему мнению. Возможно я что то не так сделал. |
|||
|
||||
| Экскалупатор |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1746 Регистрация: 1.4.2009 Где: г. Минск Репутация: 11 Всего: 24 |
я не учитывал что нужно получать данные. в таком случае нужно ждать пока закончиться прием данных, а потом все закрывать и начинать сначала. |
|||
|
||||
| uranpro |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 571 Регистрация: 7.5.2008 Где: Moscow city Репутация: 1 Всего: 1 |
из справки =) -------------------- I want a perfect soul |
|||
|
||||
| WantToProg |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 88 Регистрация: 13.4.2009 Репутация: нет Всего: нет |
Не помогает, т.к. процедура чтения данных по событию, выполняется параллельно потоку Do(). И открытие порта инициируется в этом потоке до того, как порт будет закрыт и данные будут прочитаны Чувтсвую в коде есть ошибка, но найти не знаю как. Мне все таки кажется есть возможность не выполнять цикл процедуры Do(), до тех пор, пока не будут получены данные. А вот как это сделать, очень прошу у вас совета |
|||
|
||||
| Экскалупатор |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1746 Регистрация: 1.4.2009 Где: г. Минск Репутация: 11 Всего: 24 |
uranpro, да. согласен, но тут вроде немного не так все. тут смысл в том что в одном потоке открывается порт, а второй поток этот открытый порт использует(ну на сколько я понял из объяснений). получается что второй поток зависит от первого но он об этом не знает. отсюда и лезет ошибка.
но ведь это не правильно? на сколько я понимаю сначала идет отправка чего то в порт, а потом читается ответ. ну так надо так и сделать этот процесс: открыть порт отправить прочитать ответ закрыть порт или ставить событие которое будет ждать команды окончания чтения из порта, и будет закрывать порт и только потом начинать новую итерацию цикла. |
|||
|
||||
| WantToProg |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 88 Регистрация: 13.4.2009 Репутация: нет Всего: нет |
Вот, вы меня отлично поняли. Открыть порт, отправить - первый поток из процедуры Do() Прочитать ответ по событию newPort.DataReceived += new SerialDataReceivedEventHandler(newPort_DataReceived); Вот тут описание работы события http://msdn.microsoft.com/en-us/library/sy...tareceived.aspx Как мне сделать, чтоб не возникло проблемы параллельного выполнения потока. Может быть вообще поток лишнее? Но тогда в какую сторону копать? |
|||
|
||||
| Экскалупатор |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1746 Регистрация: 1.4.2009 Где: г. Минск Репутация: 11 Всего: 24 |
WantToProg, я, конечно, не возьмусь утверждать, но мне кажется что поскольку ответ всегда читается после отправки, то нет никакого смысла делить этот процесс на два параллельных потока. все должно быть по порядку: открыть, отправить, прочитать, закрыть, следующая итерация. я это и пытался сказать, что деление на потоки в данном случае мне кажется бессмысленным, поскольку эти операции идут одна за другой. единственное нужно будет учесть превышение времени ожидания ответа.
|
|||
|
||||
| WantToProg |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 88 Регистрация: 13.4.2009 Репутация: нет Всего: нет |
Экскалупатор, В том то и проблема, я не знаю как сделать все это в одном потоке :(
Обработку события newPort.DataReceived, я взял с msdn. А другого варианта я даже не вижу. Если бы это был сетевой поток (NetworkStream), то я обошелся бы событием DataAvailable, но как проверить наличие данных в последовательном порту, я не знаю. И еще, дело в том, что есть другой вариант считывания данных: SerialPort.ReadExisting() Который возвращает System.String, но мне надо получить поток байтов. Для этого есть заметка в этой статье
Не понимаю как это сделать. Это сообщение отредактировал(а) WantToProg - 16.2.2010, 09:56 |
|||
|
||||
| Экскалупатор |
|
||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1746 Регистрация: 1.4.2009 Где: г. Минск Репутация: 11 Всего: 24 |
WantToProg, можно попробовать "усыпить" поток на время выполнения получения данных. ты видно пытался это сделать:
но так усыпляется тот поток в котором ты вызываешь этот метод. но при этом поток в котором открывается порт продолжает работать и закрывает порт. из MSDN
может это можно как то использовать? получается запрашиваешь число байтов, потом их считываешь, а потом продолжаешь выполнять метод. |
||||
|
|||||
| uranpro |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 571 Регистрация: 7.5.2008 Где: Moscow city Репутация: 1 Всего: 1 |
а если сделать метод не Do, а DoNext(...) и вызывать в конце DataReceived?
-------------------- I want a perfect soul |
|||
|
||||
| WantToProg |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 88 Регистрация: 13.4.2009 Репутация: нет Всего: нет |
Во, я так и сделал. В принципе работает, хотя помоему это неправильно. Думаю правильнее было бы блокировать первый поток пока не закончится второй. А проще было бы читать сразу по типу SerialPort.ReadExisting(). Только вот последовательность байтов не преобразовывая в строку. Если бы вы еще и это подсказали, был бы просто счастлив |
|||
|
||||
![]()
|
| Прежде чем создать тему, посмотрите сюда: | |
|
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :) Так же не забывайте отмечать свой вопрос решенным, если он таковым является :) Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |