Страница: 1 | 2 | 3 |
|
Вопрос: Пауза потоков
|
Добавлено: 15.03.11 21:59
|
|
Автор вопроса: andrey | ICQ: 305986093
|
Всем доброго времени суток, может кто-то сможет мне помочь в моей проблеме. Написал программу с несколькими потоками, все эти потоки (4-ре) опрашивают разные COM порты, т.е. посылают команду, обрабатывают ответ, присвоение значений переменным делаю через делегаты, потоки зациклины в do loop, с выходом из тела потока по метке, т.к. опрос портов должен вестись на всем протяжении работы программы (почти). Перед посылкой новой команды чищу буферы портов приема и отправки, после обработки ответа и перед loop вызываю sleep (threed.sleep(от 5 до 50, по разному). Наблюдаю такую хрень, то из 4 работает один поток, то 2 максимум, и вроде как другие просто не запускаются, вот тут и есть мой вопрос, от чего может происходить такая хрень, ведь всего 4 потока, допускаю как вариант пагубное влияние sleep, что может после прерывания потоку не выделяется времени.
1). От чего могут не запустится все потоки?
2). Как правильно выдержать паузу потока от 5 до 50 мс.?
P.S. Как понимаете для меня очень важны события реального времени, уже успел разочироваться в не адекватном поведении потоков и подумал вернутся к таймерам )!
С уважением Андрей.
Ответить
|
Номер ответа: 2 Автор ответа: andrey
ICQ: 305986093
Вопросов: 3 Ответов: 41
|
Профиль | | #2
|
Добавлено: 16.03.11 06:52
|
Dim bytes As Int32
Dim otvet() As String
Stop_Sbor = False
Do
Try
stop_potok = False
com.DiscardInBuffer()
com.DiscardOutBuffer()
If Stop_Sbor = True Then Exit Do
stroka = "#010" : Raiz_Buf = 10
Dim data As [ Byte] ) = System.Text.Encoding.Default.GetBytes((stroka) + Chr(&HD))
com. Write(data, 0, data.Length)
data = New [ Byte] Raiz_Buf - 1) {}
QueryPerformanceCounter(tm1)
Do While com.BytesToRead < Raiz_Buf
'value = instance.BytesToRead
Thread.Sleep(1)
QueryPerformanceCounter(tm2)
QueryPerformanceFrequency(fr)
If Format(((tm2 - tm1) / fr * 1000), "###0.000" > 200 Then
GoTo e
End If
Loop
bytes = com. Read(data, 0, data.Length)
If data(0) <> 62 And Oper = 0 Then
If data(1) <> 62 Then GoTo e
End If
ReDim otvet(bytes - 3)
For i = 1 To UBound(data) - 1 'Step -1
Impuls = Convert.ToInt32(Replace(Join(otvet), " ", "" , 16)
Call Update_Otvet(Impuls)
End If
e:
Thread.Sleep(10)
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Ошибка"
Exit Sub
End Try
Loop
stop_potok = True
Как я и писал происходит общение с Com портом в цикле.
Подобных потоков несколько, по одному на каждый порт.
В 3 потоках из 4, весь процесс описан не посредственно в теле процедуры объявленной при создании потока, а в 4 вызываются отдельные процедуры и функции из потока.
к примеру:
Flag_Stop_DCON = False
Do
If Potoki_Opros_Start = False Then Exit Do
Read_xxx1() 'Читаем блоки xxxx
If Potoki_Opros_Start = False Then Exit Do
Read_xxx2() 'Читаем блоки xxxx
If Potoki_Opros_Start = False Then Exit Do
Read_xxx3() 'Читаем блоки xxxx
If Potoki_Opros_Start = False Then Exit Do
Read_xxx4() 'Читаем блоки xxxx
loop
sleep в этом потоке вызывается по окончанию каждой процедуры в интервале от 5 до 10 мс.
Ответить
|
Номер ответа: 4 Автор ответа: andrey
ICQ: 305986093
Вопросов: 3 Ответов: 41
|
Профиль | | #4
|
Добавлено: 17.03.11 07:06
|
мда.. тяжелый случай.
Слушай "ГЕНИЙ", ты походу, что-то не понял, во первых для меня важно события реального времени, на одном порту весят 8 приборов, на опрос которых уходит порядка 150-200 мс., плюс еще три порта с приборами. Таймера как работают? в курсе, человек с большим опытом программирования? пусть у них даже будет стоять одинаковое время, второй, к примеру не запустится пока не выполнится первый, многопоточность позволяет выполнять процедуры "одновременно", поочередно переключаясь.
GoTo в данном случае служит для выхода из процедуры обработки ответа, если за указанное время ответ не пришел. Конечно можно задать время на события Read и Write и в обработчике исключения в зависимости от флага предпринять какое-то решение, которое по сути будет тем же GoTo, я решил не ждать этих исключений, пока, что.
UBound он показывает количество элементов в массиве, в моем случае можно его не использовать, т.к. есть переменная, которая показывает это количество...
Call в принципе согласен для вызова процидуры в VB.Net можно и не использовать ).
Большое спасибо хоть за какой-то ответ! Было бы не плохо, если бы ты реальные места указал, где поток может перейти в состояние Stopped, это я наблюдал с потоками, которые по какой-то не понятной причине не запускались, хотя у них должно быть состояние Unstarted или WaitSleepJoin как минимум, понимаешь?
Может поможет навести на какие-то мысли, потоки я объявляю в модуле, само тело потока размещено у меня в "форме1", а запускаю я их с "формы2", хотя я считаю, что это не каким образом не должно влиять на ту хрень которая происходит или на оборот не происходит.
p.s. В критике и сарказме не нуждаюсь, нуждаюсь в реальных советах и решение проблемы! И да SerialPort создаю кодингом.
Пока, что обхожусь тем, что запускаю повторно поток, если он по каким-то причинам перешел в состояние Stopped, хотя как он сволочь может завершится пока я ему флаг не передам (буллевую переменную, по которой он выходит с цикла и завершается).
Ответить
|
Номер ответа: 6 Автор ответа: EROS
Вопросов: 58 Ответов: 4255
|
Профиль | | #6
|
Добавлено: 17.03.11 10:46
|
Слушай "ГЕНИЙ", ты походу, что-то не понял
Ок, перейдем на ТЫ.. Это ты,по ходу, что то не понял.. Попробую изъясниться на понятном для тебя йазыке.
Твой код - классический пример говнокода! И не надо мне рассказывать как работают таймеры,com-порты и многопоточноть, поверь мне на слово - я это знаю.
GoTo в данном случае служит для выхода из процедуры обработки ответа
Ты правда думаешь что я не понимаю для чего служит GoTo и вся остальная шляпа которую ты юзаешь?
В критике и сарказме не нуждаюсь
Никакой критики и сарказма.. исключительно констатация фактов
Было бы не плохо, если бы ты реальные места указал
нуждаюсь в реальных советах и решение проблемы
После всего что ты наговорил подобным тоном? Увольте.. колупайся-ка ты сам,умник..
Ответить
|
Номер ответа: 9 Автор ответа: andrey
ICQ: 305986093
Вопросов: 3 Ответов: 41
|
Профиль | | #9
|
Добавлено: 17.03.11 12:42
|
AgentFire
Спасибо реальным пацанчикам ))
ReDim -> Array.Resize() не всегда так, код был приведен в пример, в большинстве случаев мне не нужен весь массив байт, ну так-то ты прав.
а вот за Exit Sub -> Return, это да, я как-то и не подумал о нем ))
EROS я не собираюсь оспаривать твои навыки, но твой "говно" совет, нах мне ненужен, если не чего сказать или предложить конкретного, просто воздержись от комментарий, я вроде разжевано описал, что нужно и как делаю, как сделать без потока, я знаю, и с тобой полностью согласен на счет события DataReceived, так, что без обид, сам первый задел меня, будь проще и люди подтянутся ))!!!
AgentFire Return можно использовать мне только в 3 потоках, в другом 4 без Do Loop и GoTo не обойтись, т.к. это обработка условий и исключений.
Сам вопрос остается не раскрытым:
Пока, что обхожусь тем, что запускаю повторно поток, если он по каким-то причинам перешел в состояние Stopped, хотя как он сволочь может завершится пока я ему флаг не передам (буллевую переменную, по которой он выходит с цикла и завершается).
3 из 4 потоков не запускаются, но имеют состояние Stopped, вот в чем собака зарыта!?
Поэтому мне приходится их повторно запускать.
Ответить
|
Номер ответа: 10 Автор ответа: AgentFire
ICQ: 192496851
Вопросов: 75 Ответов: 3178
|
Профиль | | #10
|
Добавлено: 17.03.11 13:03
|
andrey пишет:
без Do Loop и GoTo не обойтись
Тогда объясни мне, как же так получилось, что я обошелся без него?
- Dim bytes As Int32
- Dim otvet() As String
- Stop_Sbor = False
-
- Do
- Thread.Sleep(10)
- stop_potok = False
- Try
- com.DiscardInBuffer()
- com.DiscardOutBuffer()
-
- If Stop_Sbor = True Then Exit Do
-
- Raiz_Buf = 10
-
- Dim SendData As Byte() = System.Text.Encoding.Default.GetBytes(("#010") + Chr(&HD))
-
- com.Write(SendData, 0, SendData.Length)
-
- Dim ReadData(Raiz_Buf - 1) As New Byte
-
- Dim TimeoutSw = Stopwatch.StartNew()
- Do While com.BytesToRead < Raiz_Buf And TimeoutSw.ElapsedMiliseconds <= 200
-
- Thread.Sleep(1)
-
-
-
-
- Loop
-
- bytes = com.Read(ReadData, 0, ReadData.Length)
-
- If ReadData(0) <> 62 And Oper = 0 Then
- If ReadData(1) <> 62 Then Continue Do
- End If
- ReDim otvet(bytes - 3)
-
-
- Update_Otvet(Convert.ToInt32(Replace(Join(otvet), " "), ""), 16))
-
- End If
- Catch
- MsgBox(ex.Message, MsgBoxStyle.Critical, "Ошибка")
- Return
- End Try
- Loop
- stop_potok = True
так же внес небольшие поправки в код -_-
Ответить
|
Номер ответа: 11 Автор ответа: andrey
ICQ: 305986093
Вопросов: 3 Ответов: 41
|
Профиль | | #11
|
Добавлено: 17.03.11 13:41
|
AgentFire ну, чтож я тоже оптимизировал твой код под рабочий ))
- Dim bytes As Int32
- Dim otvet() As String
- Stop_Sbor = False
-
- Do
- Thread.Sleep(10)
- stop_potok = False
- Try
- com.DiscardInBuffer()
- com.DiscardOutBuffer()
-
- If Stop_Sbor = True Then Exit Do
-
- Raiz_Buf = 7
-
- Dim SendData As Byte() = System.Text.Encoding.Default.GetBytes(("$036") + Chr(&HD))
-
- com.Write(SendData, 0, SendData.Length)
-
- Dim ReadData(Raiz_Buf - 1) As Byte
-
- Dim TimeoutSw = Stopwatch.StartNew()
- Do While com.BytesToRead < Raiz_Buf And CLng(TimeoutSw.ElapsedMilliseconds.ToString) >= 200
-
- Thread.Sleep(1)
-
-
-
-
- Loop
-
- bytes = com.Read(ReadData, 0, ReadData.Length)
-
- If ReadData(0) <> 62 And Oper = 0 Then
- If ReadData(1) <> 62 Then Continue Do
- End If
- ReDim otvet(bytes - 3)
-
-
- Update_Otvet(Convert.ToInt32(Replace(Join(otvet), " ", ""), 16))
-
-
- Catch ex As Exception
- MsgBox(ex.Message, MsgBoxStyle.Critical, "Ошибка")
- Return
- End Try
- Loop
- stop_potok = True
Так, начнем:
- Do While com.BytesToRead < Raiz_Buf And TimeoutSw.ElapsedMiliseconds <= 200
-
- Thread.Sleep(1)
-
-
-
-
- Loop
Смысл этого цикла в том, что если за указанный промежуток времени (200 мили секунд) в буфер приема порта не чего не поступит, мы переходим по метке дабы избежать обработку ответа, т.к. у нас его нет. И еще твое условие Do While com.BytesToRead < Raiz_Buf And TimeoutSw.ElapsedMiliseconds <= 200 не робит даже, если прибор отключен и переходит дальше по листингу к обработке ответа.
' --- Немного не понял, нафига тут цикл For.
'For i = 1 To data.Length - 1 'Step -1 он там не нужен, т.к. я не писал, что именно я делаю с ответом и просто не заметил его и не вырезал, предоставленный код был урезан, только главное оставил.
1. Do Loop ты оставил.
2. Без GoTo в твоем примере, как оказалось не обойтись.
Ответить
|
Номер ответа: 15 Автор ответа: AgentFire
ICQ: 192496851
Вопросов: 75 Ответов: 3178
|
Профиль | | #15
|
Добавлено: 17.03.11 14:23
|
andrey пишет:
CLng(TimeoutSw.ElapsedMilliseconds.ToString) >= 200
Мать моя женщина, это что за нахуй?!!
andrey пишет:
Do While com.BytesToRead < Raiz_Buf And TimeoutSw.ElapsedMiliseconds <= 200 не робит даже, если прибор отключен и переходит дальше по листингу к обработке ответа. Включая мозг, внезапно обнаруживаем, что можно написать- If TimeoutSw.ElapsedMiliseconds > 200 Then Continue Do
и все вдруг "робит".
andrey пишет:
Do Loop ты оставил. Я бы таки сделал Do Until Stop_Sbor .. Loop, но имея весь код, скорее всего, делал бы через ThreadPool и БЕЗ Do-Loop. В том урезке говнокода, что ты дал, без ду-лупа, действительно, не айс.
andrey пишет:
Тут переход работает, но минует Sleep Не минует, потому что слип стоит в начале цикла.
___________________
You see, именно потому что твой код - говно, а стиль написания и внимательность находятся на зарождающемся уровне, и нуждаются в неплохой доработке, именно поэтому и Эрос, и я, и может кто еще обязательно скажут тебе идти и учить основы прогрмамирования на дотнете. Та же вики говорит, что в переходе с шестерки на .net сменился сам стиль программирования, и то, что считалось крутым в vb6, здесь выглядит смешно и до несмешного убого. -_-
Ответить
|
Страница: 1 | 2 | 3 |
Поиск по форуму