Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - .NET

Страница: 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. Как понимаете для меня очень важны события реального времени, уже успел разочироваться в не адекватном поведении потоков и подумал вернутся к таймерам )!
С уважением Андрей.

Ответить

  Ответы Всего ответов: 37  

Номер ответа: 1
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #1 Добавлено: 16.03.11 00:07
потоки зациклины в do loop

вот с этого места подробней.. что делается в этом цикле?

Ответить

Номер ответа: 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 мс.

Ответить

Номер ответа: 3
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #3 Добавлено: 17.03.11 01:46
мда.. тяжелый случай.
Я,так полагаю, опыт программирования совсем небольшой? И исключительно на VB6?
В вашем коде наберется с десяток мест, в которых поток может тупо повиснуть в бесконечном ожидании.. более того, в вашем случае потоки абсолютно не нужны.. SerialPort поддерживает ассинхронное получение данных через событие DataReceived.. Почитайте для начала документацию по языку и платформе что вы используете..
Конструкции вида GoTo,UBound,Call уже не используют лет 300..
И да, вот еще.. отделите мух от котлет.. работу с портом от обработки полученных данных.. выкиньте все лишнее,тогда многое станет понятнее..

Ответить

Номер ответа: 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, хотя как он сволочь может завершится пока я ему флаг не передам (буллевую переменную, по которой он выходит с цикла и завершается).

Ответить

Номер ответа: 5
Автор ответа:
 andrey



ICQ: 305986093 

Вопросов: 3
Ответов: 41
 Профиль | | #5 Добавлено: 17.03.11 07:16
Так к слову, 150-200 мс. это только время: посылка - ответ, не включающая в себя обработку этого ответа.

Ответить

Номер ответа: 6
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #6 Добавлено: 17.03.11 10:46
Слушай "ГЕНИЙ", ты походу, что-то не понял

Ок, перейдем на ТЫ.. Это ты,по ходу, что то не понял.. Попробую изъясниться на понятном для тебя йазыке.
Твой код - классический пример говнокода! И не надо мне рассказывать как работают таймеры,com-порты и многопоточноть, поверь мне на слово - я это знаю.
GoTo в данном случае служит для выхода из процедуры обработки ответа

Ты правда думаешь что я не понимаю для чего служит GoTo и вся остальная шляпа которую ты юзаешь?
В критике и сарказме не нуждаюсь

Никакой критики и сарказма.. исключительно констатация фактов
Было бы не плохо, если бы ты реальные места указал

нуждаюсь в реальных советах и решение проблемы

После всего что ты наговорил подобным тоном? Увольте.. колупайся-ка ты сам,умник..

Ответить

Номер ответа: 7
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #7 Добавлено: 17.03.11 11:53
реальный код для реальный пацанчиков.

начни с этого:
  1. ...
  2. Try
  3.     stop_potok = False
  4. ...

->
  1. ...
  2. stop_potok = False
  3. Try
  4. ...

Ответить

Номер ответа: 8
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #8 Добавлено: 17.03.11 11:56
Затем по списку
  1. ReDim -> Array.Resize()
  2. Exit Sub -> Return
  3. UBound() -> .Length - 1

и т.п.

Ответить

Номер ответа: 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 не обойтись


Тогда объясни мне, как же так получилось, что я обошелся без него?
  1.         Dim bytes As Int32
  2.         Dim otvet() As String
  3.         Stop_Sbor = False
  4.  
  5.         Do
  6.             Thread.Sleep(10)
  7.             stop_potok = False
  8.             Try
  9.                 com.DiscardInBuffer()
  10.                 com.DiscardOutBuffer()
  11.                 ' --- Наверное, здесь должна быть stop_potok ?..
  12.                 If Stop_Sbor = True Then Exit Do
  13.  
  14.                 Raiz_Buf = 10
  15.  
  16.                 Dim SendData As Byte() = System.Text.Encoding.Default.GetBytes(("#010") + Chr(&HD))
  17.  
  18.                 com.Write(SendData, 0, SendData.Length)
  19.  
  20.                 Dim ReadData(Raiz_Buf - 1) As New Byte
  21.                 'QueryPerformanceCounter(tm1)
  22.                 Dim TimeoutSw = Stopwatch.StartNew()
  23.                 Do While com.BytesToRead < Raiz_Buf And TimeoutSw.ElapsedMiliseconds <= 200
  24.                     'value = instance.BytesToRead
  25.                     Thread.Sleep(1)
  26.                     'QueryPerformanceCounter(tm2)
  27.                     'QueryPerformanceFrequency(fr)
  28.                     ' --- Видимо, тут ты хотел запилить супер-мега таймаут в .2 сек.
  29.                     'If Format(((tm2 - tm1) / fr * 1000), "###0.000") > 200 Then Exit Do
  30.                 Loop
  31.                 
  32.                 bytes = com.Read(ReadData, 0, ReadData.Length)
  33.                 
  34.                 If ReadData(0) <> 62 And Oper = 0 Then
  35.                     If ReadData(1) <> 62 Then Continue Do
  36.                 End If
  37.                     ReDim otvet(bytes - 3)
  38.                     ' --- Немного не понял, нафига тут цикл For.
  39.                     'For i = 1 To data.Length - 1 'Step -1
  40.                     Update_Otvet(Convert.ToInt32(Replace(Join(otvet), " "), ""), 16))
  41.                     'Next
  42.                 End If
  43.             Catch
  44.                 MsgBox(ex.Message, MsgBoxStyle.Critical, "Ошибка")
  45.                 Return
  46.             End Try
  47.         Loop
  48.         stop_potok = True
так же внес небольшие поправки в код -_-

Ответить

Номер ответа: 11
Автор ответа:
 andrey



ICQ: 305986093 

Вопросов: 3
Ответов: 41
 Профиль | | #11 Добавлено: 17.03.11 13:41
AgentFire ну, чтож я тоже оптимизировал твой код под рабочий ))
  1. Dim bytes As Int32
  2.         Dim otvet() As String
  3.         Stop_Sbor = False
  4.  
  5.         Do
  6.             Thread.Sleep(10)
  7.             stop_potok = False
  8.             Try
  9.                 com.DiscardInBuffer()
  10.                 com.DiscardOutBuffer()
  11.                 ' --- Наверное, здесь должна быть stop_potok ?..
  12.                 If Stop_Sbor = True Then Exit Do
  13.  
  14.                 Raiz_Buf = 7
  15.  
  16.                 Dim SendData As Byte() = System.Text.Encoding.Default.GetBytes(("$036") + Chr(&HD))
  17.  
  18.                 com.Write(SendData, 0, SendData.Length)
  19.  
  20.                 Dim ReadData(Raiz_Buf - 1) As Byte
  21.                 'QueryPerformanceCounter(tm1)
  22.                 Dim TimeoutSw = Stopwatch.StartNew()
  23.                 Do While com.BytesToRead < Raiz_Buf And CLng(TimeoutSw.ElapsedMilliseconds.ToString) >= 200
  24.                     'value = instance.BytesToRead
  25.                     Thread.Sleep(1)
  26.                     'QueryPerformanceCounter(tm2)
  27.                     'QueryPerformanceFrequency(fr)
  28.                     ' --- Видимо, тут ты хотел запилить супер-мега таймаут в .2 сек.
  29.                     'If Format(((tm2 - tm1) / fr * 1000), "###0.000") > 200 Then Exit Do
  30.                 Loop
  31.  
  32.                 bytes = com.Read(ReadData, 0, ReadData.Length)
  33.  
  34.                 If ReadData(0) <> 62 And Oper = 0 Then
  35.                     If ReadData(1) <> 62 Then Continue Do
  36.                 End If
  37.                 ReDim otvet(bytes - 3)
  38.                 ' --- Немного не понял, нафига тут цикл For.
  39.                 'For i = 1 To data.Length - 1 'Step -1
  40.                 Update_Otvet(Convert.ToInt32(Replace(Join(otvet), " ", ""), 16))
  41.                 'Next
  42.  
  43.             Catch ex As Exception
  44.                 MsgBox(ex.Message, MsgBoxStyle.Critical, "Ошибка")
  45.                 Return
  46.             End Try
  47.         Loop
  48.         stop_potok = True

Так, начнем:
  1.   Do While com.BytesToRead < Raiz_Buf And TimeoutSw.ElapsedMiliseconds <= 200
  2.                      'value = instance.BytesToRead
  3.                      Thread.Sleep(1)
  4.                      'QueryPerformanceCounter(tm2)
  5.                      'QueryPerformanceFrequency(fr)
  6.                      ' --- Видимо, тут ты хотел запилить супер-мега таймаут в .2 сек.
  7.                      'If Format(((tm2 - tm1) / fr * 1000), "###0.000") > 200 Then Exit Do
  8.                  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 в твоем примере, как оказалось не обойтись.

Ответить

Номер ответа: 12
Автор ответа:
 andrey



ICQ: 305986093 

Вопросов: 3
Ответов: 41
 Профиль | | #12 Добавлено: 17.03.11 13:49
Ребят, я благодарен за примеры альтернативного кодинга, если, что-то реально меняет ситуацию в лучшую сторону по времени, я только за, и даже буду пользоваться альтернативой )), но основной вопрос, то открыт!!!
  1. Dim TimeoutSw = Stopwatch.StartNew()
  2.                 CLng(TimeoutSw.ElapsedMilliseconds.ToString) >= 200
вот это я позже посмотрю, что это и с чем его едят )).

Ответить

Номер ответа: 13
Автор ответа:
 andrey



ICQ: 305986093 

Вопросов: 3
Ответов: 41
 Профиль | | #13 Добавлено: 17.03.11 13:50
И кстати Return , каким образом мне поможет?

Ответить

Номер ответа: 14
Автор ответа:
 andrey



ICQ: 305986093 

Вопросов: 3
Ответов: 41
 Профиль | | #14 Добавлено: 17.03.11 14:08
  1. If ReadData(0) <> 62 And Oper = 0 Then
  2.                      If ReadData(1) <> 62 Then Continue Do
  3.                  End If
Тут переход работает, но минует Sleep, из-за этой не прерывной работы потока, он может сжирать много процессорного времени, хотя в принципе его можно оставить, т.к. ответ от прибора был хоть и кривой.

Ответить

Номер ответа: 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 не робит даже, если прибор отключен и переходит дальше по листингу к обработке ответа.
Включая мозг, внезапно обнаруживаем, что можно написать
  1. 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 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам