Имя: Пароль:
IT
 
знатокам многопоточности: как корректно завершить отдельный поток?
0 vde69
 
12.05.16
21:59
язык не важен все равно используется вин апи... что-то не выходит у меня, подвисает при попытке закрыть дискрипторы

поток создаю так:

-------------------------------------------------------------------
// сам поток
procedure DoEvent ();
begin
while hPort > 0 do begin
   try
     // тут крутится чтение порта
     WaitCommEvent(hPort, mask, nil);
     ClearCommError(hPort, temp, @comstat);

     ReadFile(hPort, Buf[BufEnd], 255 - BufEnd, temp, nil);

--------------------------------------------------------------------
// запуск потока
  CommThread:= CreateThread(nil, 0, @DoEvent, nil, 0, ThreadID);

--------------------------------------------------------------------
// остановка потока
  if hPort > 0 then CloseHandle(hPort);
  if CommThread > 0 then CloseHandle(CommThread);
1 NorthWind
 
12.05.16
22:01
в каком именно месте виснет?
2 NorthWind
 
12.05.16
22:03
я закрываю примерно также, ничего не виснет
    if (FComHandle && FComHandle != INVALID_HANDLE_VALUE) {
        CloseHandle (FComHandle);
        FComHandle = NULL;
    }
но у меня тред унаследован от VCLного TThread, поэтому вторую конструкцию как у вас я не делаю
3 Лефмихалыч
 
12.05.16
22:04
4 vde69
 
12.05.16
22:04
после выполнения
if hPort > 0 then CloseHandle(hPort);
if CommThread > 0 then CloseHandle(CommThread);

но точное место - не скажу, по тому как виснет как-то хитро :)
5 NorthWind
 
12.05.16
22:05
(4) я вижу, что код у вас на дельфи. Не хотите от TThread поток унаследовать? Все-таки там попроще будет, можно сосредоточиться на "своей" задаче
6 Лефмихалыч
 
12.05.16
22:06
(4) потому, что сначала надо вызвать или ExitThread, или ExitProcess, или TerminateThread или TerminateProcess, как я понял
7 NorthWind
 
12.05.16
22:07
(6) -> (5). Библиотека возьмет это на себя, достаточно сделать Terminate () треду.
8 Лефмихалыч
 
12.05.16
22:08
(7) суть не меняется
9 NorthWind
 
12.05.16
22:10
(8) меняется, там в библиотеке уже все это решено, просто наследуешься от стандартного TThread и пишешь свой код, главное чтобы он был потокобезопасным. А все CreateThread и ExitThread спрятаны.
10 Лефмихалыч
 
12.05.16
22:13
(9) этот твой Terminate() в итоге вызывает тот же самый TerminateThread().
Я согласен с тем, что унаследовать реализацию работы с потоками и заняться бизнес-логикой - это гораздо разумнее. Но вопрос у автора не в этом, а в том, чо эта падла виснет
11 NorthWind
 
12.05.16
22:14
(10) понятное дело. Я просто вижу, что код у него на дельфи, и подсказываю рабочий вариант, чтобы двор ломом не подметать. Тем более что к дельфям в стандартных примерах идет пример работы с TThread.
12 NorthWind
 
12.05.16
22:17
Лет 15 назад я за какой-то вечер легко написал читалку с электронных весов через COM, которая синхронизировалась с основным потоком, показывала дисплей весов в форме и даже не жрала ресурсы и не падала (!). Все благодаря TThread.
13 H A D G E H O G s
 
12.05.16
22:21
TThread горит синим пламенем.

Я лучше сам все сделаю с ~шлюхами и блэкджеком~ мьютексами и критическими секциями.
14 vde69
 
12.05.16
22:28
вроде от зависона избавился, проблема была в перекрёстном использовании дискритпторов, через TerminateThread

там другие проблемы появились, но это уже на завтра...
15 H A D G E H O G s
 
12.05.16
22:34
IsMultiThread:=true;

Я надеюсь, это есть.
16 H A D G E H O G s
 
12.05.16
22:36
Воот тут немного о том, почему надо давать потоку умереть самому.

http://www.transl-gunsmoker.ru/2010/09/windows-xp.html

Будь мужиком, убивай поток выходом из функции потока по флагу!
17 Кирпич
 
12.05.16
22:37
(0) сначала прекрати бесконечный цикл в потоке, потом CloseHandle(hPort);
(10) Terminate() ничего не вызывает. он вроде просто ставит флаг, что поток надо завершать, а сам поток проверяет этот флаг.

while not Terminated do
     WaitCommEvent(hPort, mask, nil);
     ClearCommError(hPort, temp, @comstat);

     ReadFile(hPort, Buf[BufEnd], 255 - BufEnd, temp, nil);
end;
18 NorthWind
 
12.05.16
22:40
(17) если у него сделано на WinAPI, ему еще нужно как минимум завершить поток и убить его. Если TThread, то все верно написано - пока не Terminated, будет крутиться функция потока, а потом деструктор который сам сделает все что надо.
19 Кирпич
 
12.05.16
22:49
Ну я так и написал. А глючит потому что он в одгом потоке дескриптор грохнул, а в другом его же юзает
20 Fragster
 
гуру
12.05.16
22:53
на 1с проще :)
21 NorthWind
 
12.05.16
23:33
(20) зато на Паскале или плюсах - веселее :)
22 NorthWind
 
12.05.16
23:34
Особенно на winapi, как ТС - до конца никогда нет уверенности, что все делаешь правильно ;) кстати, статья в (16) - отличная
23 Pixelrat
 
12.05.16
23:45
(16) +100500
24 H A D G E H O G s
 
13.05.16
00:00
(22) Gunsmokera можно читать вообще всегда.
Там квинтэссенция разума.
25 H A D G E H O G s
 
13.05.16
00:05
26 H A D G E H O G s
 
13.05.16
00:09
27 H A D G E H O G s
 
13.05.16
00:11
28 H A D G E H O G s
 
13.05.16
00:13
Ну и конечно, проблемы говнокода - это не только проблемы 1Сников :-)
http://www.gunsmoker.ru/2010/05/90.html
29 H A D G E H O G s
 
13.05.16
00:17
В ветке (28) - отличный, охеренно годный пример того, с чем сталкивается каждый программист на Delphi/ИТемБолееC++ и никогда не столкнется программист 1С. Это пример с Base64.
Ну и еще вот:
http://local.joelonsoftware.com/wiki/Абсолютный_Минимум,_который_Каждый_Разработчик_Программного_Обеспечения_Обязательно_Должен_Знать_о_Unicode_и_Наборах_Символов

За эти 2 момента надо боготворить 1С :-)
32 H A D G E H O G s
 
13.05.16
00:44
(31) Это ты мне?
33 orefkov
 
13.05.16
00:46
(29)
Боюсь охладить ваш оптимизм, но в полноценный юникод 1С не умеет :(
35 H A D G E H O G s
 
13.05.16
00:54
(33) Я знаю. Я не об этом, я про другое.
Я про то, что 1С нику не надо любиться с
МассивомСимволов
КороткимиСтроками
null-терминэйт строками
указателями на строку
delphi строками

все вышеперечисленное в разрезе Ansi/Wide.
И не забываем про bstr строки, а также winapi - списки.
36 orefkov
 
13.05.16
00:55
По теме ветки - гарантированно корректно завершить поток извне самого потока невозможно. Прервать, убить - можно, но в общем случае это не корректно. По канону надо как-либо передать потоку признак того, что ему надо завершится. Как конкретно это реализуется - зависит от конкретной задачи.
37 orefkov
 
13.05.16
01:00
(34)
Это да, весь секас спрятан от одинэсника под капотом. Как плата за это одинэсник должен довольствоваться только одной миссионерской позой, прописанной в жёлтокрасном катехизисе с непременным использованием одобренного производителем презерватива :)
38 H A D G E H O G s
 
13.05.16
01:06
(37) Я был бы щастлив, если бы и в других ЯП было бы также со строками. Один стандарт. Раз, и все старое отменили бы, были бы прекрасные Дельфи строки с длинной в заголовке и счетчиком ссылок.
39 mehfk
 
13.05.16
04:20
(38) >> были бы прекрасные Дельфи строки
фу, какая мерзость :)
40 spock
 
13.05.16
06:13
(36) +1
Завершать поток внутри потока, а не снаружи.
41 Pixelrat
 
13.05.16
08:20
(35) Про multibyte-то и забыли.
(38) Пока одни мечтают, другие пользуются.
42 spock
 
13.05.16
08:39
(38) У такого подхода хранения строк есть и минусы.
43 arsik
 
гуру
13.05.16
09:28
(42) За то сколько плюсов ...
44 vde69
 
13.05.16
14:17
а почему у меня не работает чтение?

OverRead.hEvent := CreateEvent(nil, True, False, nil);
while MainForm.COM_RUN do begin
   try
     WaitCommEvent(MainForm.hPort, mask, @OverRead);
     // Re-specify the set of events to be monitored for the port.
     SetCommMask (MainForm.hPort, EV_RXCHAR + EV_CTS + EV_DSR + EV_RING);
     if mask >= EV_RXCHAR then
       begin
         ReadFile(MainForm.hPort, Buf[BufEnd], 1, temp, nil);
         if temp <> 1 then Continue;
//сюда никогда не попадаю !!!!
45 vde69
 
13.05.16
14:19
(44) +
а в терминале данные идут...

предполагаю дело в инициализации порта, но чего смотреть не понимаю, вроде ни каких ошибок нет, события генерятся (в том числе и EV_RXCHAR) но данные не читаются ...
46 Кирпич
 
13.05.16
14:35
(44) а шо такое  Buf[BufEnd]?

мож так надо?
@Buf[BufEnd]
47 Кирпич
 
13.05.16
14:38
а вабще, для работы с портом есть synaser.pas
http://www.ararat.cz/synapse/
48 vde69
 
13.05.16
14:38
(46) это элемент массива с типом byte, по факту это и есть указатель
49 Кирпич
 
13.05.16
14:40
(48) байт не может быть указателем. маловат. собаку то подставь.
50 vde69
 
13.05.16
14:44
(49) дельфи все равно передает не по значению а по ссылке.
а с сабакой все равно ругается...
51 Кирпич
 
13.05.16
14:50
(50) не выдумывай про дельфи. это только если var перед параметром написано.
Поглядел. Собаку не надо.
52 vde69
 
13.05.16
14:52
оставлю здесь лучшую ссылку про сом порты в дельфи http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=1126
53 Кирпич
 
13.05.16
15:04
(52) ну так и делай как там написано :) зачем здесь спрашивать.
ну или хотя бы свой код выложи. как люди то догадаются где ты накосячил.
54 Сверчок
 
13.05.16
15:27
(43) В самом деле: за что столько плюсов?

В который уж раз говорено: человек не способный управляться даже с родным языком никогда не сможет должным образом управиться с языком искусственным. Безграмотный программист -- нонсенс и сигнал тревоги работодателю. Что ж, практика в очередной раз подтверждает...
55 Жан Пердежон
 
13.05.16
15:41
(54) самое главное - не забыть побрюзжать
56 Serginio1
 
13.05.16
15:44
(36)
Лучше всего проверять флаг в потоке.

Можно  Бросить исключение в потоке ThreadAbort, но в потоке нужно обрабатывать исключение ThreadAbortException для ракрытия ресурсов и правильного выхода.
(38) В .Net один вид строки.
Кстати
У меня к тебе вопрос по Native ВК
Можно ли передать ссылку на ВК в качестве параметра. Если да то какой тип Варианта передается, и можно ли такой тип вернуть передав созданный наследник IComponentBase
57 vde69
 
13.05.16
15:48
(56) это будет адрес, только вот не понятно зачем он тебе? если это в пределах одного модуля - то все довольно легко,
а если пытаться работать с адресом чужого модуля - тут все сложно...
58 Serginio1
 
13.05.16
15:54
(57) Сделать обертку над объектами.
Неспешно ищу работу. 1С + .Net
59 Serginio1
 
13.05.16
15:56
А по поводу языка и его важности. Вот элеметарный примемер использования КомПорта только средствами 1С
http://catalog.mista.ru/public/417830/
60 Жан Пердежон
 
13.05.16
16:10
любопытства ради, скажите чем плох TThread?
в студенческие двухтысячные только его и юзали
61 NorthWind
 
13.05.16
16:23
(60) Мне кажется, ничем особенно не плох. Утечек ресурсов сам по себе не дает. У меня есть решения, где работает уже много лет и особенно пожаловаться не на что.
62 NorthWind
 
13.05.16
16:24
да и в стандартных VCL компонентах он используется
63 Кирпич
 
13.05.16
16:30
(60) да это человек такой. он хочет программировать паяльником, но так как windows не разрешает, приходится на winapi тупить.
64 Кирпич
 
13.05.16
16:31
(63) на меня тоже иногда находит такое :)
65 H A D G E H O G s
 
13.05.16
17:18
(56) я не в курсе, сорри.
Я как узнал, что 1с не передает диспатч в вк - загрустил.
И стал писать аналоги дз, тз, сз на дельфи.
А потом их сериализаторы в xdto.
Осилил сз и совсем загрустил.

А потом нормально допилил com вк, чтобы она вообще забыла про существование реестра винды и привеселел.

Ну а линукс? Я поговорился с внутренним перфекционичтом считать ее недоОС.
И мы счастливы.
66 Asmody
 
13.05.16
17:31
(65) Минкомсвязи со своими инициативами отечественного ПО скоро постучится в твою дверь.
67 Serginio1
 
13.05.16
17:33
(65) Я просто заинтересовался использованием классов .Net на линуксе через пайпы.
Но для этого ВК должна возвращать ссылку на ВК и передавать её в прараметрах.
68 Serginio1
 
13.05.16
17:34
(66) Пока только для гос учреждений. На бизнес это не распространяется.
69 Pixelrat
 
13.05.16
18:09
Нет оси кроме OS X и BSD предвестник ея!
70 Serginio1
 
14.05.16
08:33
(65) Кстати, а как забыла про реестр?
Тут два пути.
1. Прописать ветку в HKLU http://www.cyberforum.ru/visual-basic/thread649325.html
2. Зная GUID и путь загрузить объект из DLL v8: v8: Использование сборок .NET в 1С 7.x и 8.x
71 H A D G E H O G s
 
14.05.16
10:11
(70) "Зная GUID и путь загрузить объект из DLL"

Путь верный, только там все на порядки сложнее.
72 vde69
 
16.05.16
16:48
следующий вопрос по сабжу:

чем победить "зависания" связанные с большим входящим потоком и тормозами вывода данных на экран?

зы
это я написал генератор шума на скорости 19600 и мое двупоточное приложение зависло :) вроде приемка и разбор пакетов справляются а вот визуальная часть - нет.

ззы
понятно, что можно выводить в файл а не на экран, но это не по мне
73 vde69
 
16.05.16
16:50
+ связь между потоками идет через PostMessage()
74 mistеr
 
16.05.16
17:05
(72) Кольцевой буфер в виде mapped file. PostMessage() в топку.

А если буфера не хватает, то дропать пакеты, тут ничего не поделаешь.
75 mistеr
 
16.05.16
17:08
(74) P.S. Всю ветку не читал
76 Serginio1
 
16.05.16
17:13
(71) Ну подскажи куда копать? Понятно, что для этого нужна ВК или COM.
77 H A D G E H O G s
 
16.05.16
17:13
во что на экран выводишь?
78 Serginio1
 
16.05.16
17:14
(72) Зачем тебе все выводить на Экран. Ты в Мемо загрузаешь или куда?
79 Кирпич
 
16.05.16
17:20
неиначе биткоины генерит, антихрист
80 Тыковка Е
 
16.05.16
17:31
(66) Был на круглом столе по импортозамещению в сфере ИТ. Курс направлен только на гос.сектор. При попытке повузмущаться, что как на счет потребностей частного сектора, сказали что забудьте, нам это не интересно - масштабы не те. Выхлоп конечно можно и больше получить, но гемора много, надо работать и попилить нет возможности.
81 H A D G E H O G s
 
16.05.16
17:32
(80) "и попилить нет возможности."

так прямо и сказали?
82 Тыковка Е
 
16.05.16
17:33
(72) Самое интересное, что ты хочешь успеть увидеть на экране, у тебя глаз такую скорость вывода способен распознать? Дели вывод данных, например каждый 1000-ый блок.
83 Тыковка Е
 
16.05.16
17:34
(81) Ну я немного от себя добавил :)
84 vde69
 
16.05.16
21:30
(77) на экран вывожу уже распознанные пакеты, пока гружу в мемо... которое очищаю с начала свыше 100 строк
(74) хороший вариант, публикуемый в память файл фиксированной длины, но проблема в том, что у меня блоки переменной длинны и уже разобранные... разбирать заново лишние затраты.


в целом такой поток - это скорее нештатная ситуация для меня, но мне нужен инструмент который поможет понять причину такого поведения оборудования, понять можно по некому дампу, по этому самым лучшим вариантом будет вывод блоками, но в обычном режиме (и с фильтрами) трафик будет примерно 5 пакетов в секунду, хочется както понимать где надо дропать а где нет...
85 H A D G E H O G s
 
16.05.16
21:32
(84) Про BeginUpdate()/EndUpdate() даже можно не спрашивать?
86 vde69
 
16.05.16
21:39
(85) пока не делал, но думал на эту тему, завтра попробую начать с этого.

Хочу сделать специальное меседжер для отправки необходимости обработать некий более большой блок целиком, в том числе и с визуализацией
87 vde69
 
16.05.16
21:41
(86) а когда событие не генерится - будет таймер работать...

кстати таймер - единственный вариант который я вижу для отслеживания необходимости дропать - при перегрузки таймер не срабатывает по этому отсутствие события от таймера можно использовать как событие для перехода в "режим дропа"
88 mistеr
 
16.05.16
23:16
(84) >публикуемый в память файл фиксированной длины, но проблема в том, что у меня блоки переменной длинны и уже разобранные... разбирать заново лишние затраты.

Что-то не вижу проблемы. Причем тут размеры блоков и их "разобранность"?

>трафик будет примерно 5 пакетов в секунду, хочется както понимать где надо дропать а где нет...

С таким трафиком дропать ничего не придется. :)

>гружу в мемо
ListView - рекомендации лучших собаководов. (Process Monitor видел?)
89 H A D G E H O G s
 
16.05.16
23:24
(88) TNextGrid за 89 баксов :-)
90 Кирпич
 
16.05.16
23:36
Шоу телепатов продолжается :)
Form1.Canvas.TextRect хватит. Чо там разглядывать? Цифарки как в кино про матрицу?
91 Кирпич
 
16.05.16
23:38
(0)А нафига этот генератор шума нужен? Чо им делать то?
92 Боровик Сергей
 
17.05.16
01:41
(0) поток должен завершиться сам. Ему нужно сигнализировать о том что ему следует завершиться. Поток время от времени должен проверять нет ли сигнала.

Последовательность таков
1) Сигнализируем
3) WaitForSingleObject(ХендлПотока)
2) CloseHandle(ХендлПотока);
93 Боровик Сергей
 
17.05.16
01:42
(0) И чтение из COM порта сделайте перекрытым
94 Pixelrat
 
22.05.16
22:22
http://xydan.livejournal.com/8595.html - может быть будет полезной.
Я не хочу быть самым богатым человеком на кладбище. Засыпать с чувством, что за день я сделал какую-нибудь потрясающую вещь — вот что меня интересует. Стив Джобс