Страница: 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 | 
 
		
			Поиск по форуму