PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Столкнулся возможно с глюком потока ?


Столкнулся возможно с глюком потока ?

Сообщений 1 страница 20 из 20

1

Собственно пример с этого форума:

Код:
Enumeration 
  #Window_0 
  #Start
  #Text 
EndEnumeration 

Procedure Progr(*x)
  For a=0 To 100000
  SetGadgetText(#Text,Str(a))
  Delay(100)
  Debug "Жив1"
 Next    
EndProcedure  
  
    
OpenWindow(#Window_0, 100, 150, 400, 200, "Работа в потоке",#PB_Window_SystemMenu|#PB_Window_WindowCentered) 
 ButtonGadget(#Start,20,50,70,20,"Старт")   
 TextGadget(#Text, 150,50, 30,20,"")

  Repeat 
    Event = WaitWindowEvent() 
    If Event = #PB_Event_Gadget    
      Select EventGadget() 
        Case #Start  

              If IsThread(ThreadID)=0
               ThreadID=CreateThread(@Progr(), x)
             Else
               Delay (2000)
               MessageRequester("", "Программа занята!", #MB_OK|#MB_ICONWARNING)
              EndIf  

      EndSelect 
    EndIf               
  Until Event = #PB_Event_CloseWindow

Суть - при повторном нажатии Старт поток встает пока не пройдет Delay.
Затык в SetGadgetText.
Как быть ?

Отредактировано Alexsvc (24.03.2017 14:31:09)

0

2

Это особенность винды. SetGadgetText под виндой использует функцию SendMessage предусматривающую гарантированную доставку сообщения (или функция вернет код ошибки если ей это не удастся). Сообщения доставляются при вызове WaitWindowEvent(), по одному сообщению на вызов. Задержка в основном цикле программы - не самое лучшее решение, поскольку в это время "виснут" окна программы и если задержка слишком большая, то винда сообщит что программа не отвечает.

0

3

Спасибо за ответ.
А есть возможность кроме WaitWindowEvent() передать управление во внешние потоки ?
Ситуация в том, что требуется внешние потоки поставить на паузу, но только в том месте где они (потоки) не обращаются к общим данным. Если этого не сделать наступает коллизия данных.
При обработке главного потока  они виснут и  "подождать" из невыходит. Долбить  WaitWindowEvent() - потеря разных эвентов и сильный тормоз интерфейса.
Выходит что выход только в том чтобы  изолировать вывод в интерфейс  в отдельный поток с изоляцией его данных ?

0

4

Вышел из положения долблением WindowEvent() до тех пор пока все процессы не лягут в паузу. Хот и теряю эвенты, но зато все работает и достаточно быстро.
Уж и попортило мне нервов эта "особенность" винды. Думаю имеет право занесения этой особенности в хелп.

0

5

Alexsvc написал(а):

Уж и попортило мне нервов эта "особенность" винды.

В винде хоть как-то работает. В Linux такие действия приводят в вылету программы - GTK не поддерживает многопоточность.

Можно сделать по другому (несколько усложнив программу). Вместо выполнения SetGadgetText в потоке, нужно сгенерировать событие функцией PostEvent и в основном потоке (в котором создано окно) обрабатывать его.

Код:
Enumeration 
  #Window_0 
  #Start
  #Text 
EndEnumeration 

Enumeration #PB_Event_FirstCustomValue
  #Event
EndEnumeration

Procedure Progr(*x)
  For a=0 To 100000
    PostEvent(#Event, #Window_0, #Text, 0, a)
    Delay(100)
    Debug "Жив1"
  Next    
EndProcedure  


OpenWindow(#Window_0, 100, 150, 400, 200, "Работа в потоке",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
ButtonGadget(#Start,20,50,70,20,"Старт")   
TextGadget(#Text, 150,50, 30,20,"")

Repeat 
  Event = WaitWindowEvent() 
  If Event = #PB_Event_Gadget    
    Select EventGadget() 
      Case #Start  
        
        If IsThread(ThreadID)=0
          ThreadID=CreateThread(@Progr(), x)
        Else
          Delay (2000)
          MessageRequester("", "Программа занята!", #MB_OK|#MB_ICONWARNING)
        EndIf  
        
    EndSelect 
    
  ElseIf Event = #Event
    SetGadgetText(EventGadget(),Str(EventData()))
  EndIf               
Until Event = #PB_Event_CloseWindow

0

6

Еще раз благодарю за помощь!
:cool:

0

7

Что-то никак не могу понять причину глюка.
В основном потоке передаю байт в процедуру, которая записывает его в кольцевой буфер (глобальный массив).
Когда буфер заполняется (счётчик записи становится равным счётчику чтения), процедура зацикливается, ожидая, когда они перестанут быть равны.
В дополнительном потоке данные считываются из буфера (медленнее, чем заполняются).
Но в момент когда счётчики сравниваются, поток останавливается.
Коллизии доступа к данным разруливал и мьютексами и семафорами.
Результат одинаковый.
Также пробовал изменять условие для вспомогательной ветки процедуры (не равны, а например счётчик записи равен счётчику чтения минус сколько-то).
Может есть какие-то тонкости работы с потоками-семафорами-мьютексами?

0

8

Gregory написал(а):

В основном потоке передаю байт в процедуру, которая записывает его в кольцевой буфер (глобальный массив).
Когда буфер заполняется (счётчик записи становится равным счётчику чтения), процедура зацикливается, ожидая, когда они перестанут быть равны.

Как красиво описал! Прямо Л. Толстой от информатики.
Но лучше бы кусочек кода :)

0

9

ВиниПур написал(а):

Но лучше бы кусочек кода

Как скажите (но только кусочек):

Код:

Procedure  ThreadCOMportAndLogger(*ParmatCOM)

    Protected DebugSendBytesCounter.w = 0
    Protected DebugRecieveBytesCounter.w = 0
    Protected Temp.a
    Protected Temp$
    Protected VolCleareCounterActiveSensingProcedCOM.a
    Protected CounterIntervalSendByteProcedCOM.a, ValIntervalSendByteProcedCOM.a, VolCleareCounterIntervalSendByteProcedCOM.a
    Protected CounterLimitTimeComPortSendProcedCOM.a, VolCleareCounterLimitTimeComPortSendProcedCOM.a

    Protected VolSendMessage.a
    Protected VolRunningStatusProced.a
    Protected CounterStatusBytesRunningStatusLimitLow.a = 0
    Protected CounterStatusBytesRunningStatusLimit.a = 0
    Protected VolWriteToComPortProced.a = 0
    Protected VolDrumChannelSendProced.a, ValDrumChannelSendProced
    Protected TimeSendRealTimeString$ = FormatDate ("%hh:%ii:%ss", Date())
    Protected VolLoggerWriteOutputRealTime.a = 0
    Protected VolLoggerWriteOutputMessage.a = 0
    Protected ValBytesInMessageOut.a = 3
    Protected ValBytesInMessageRealOut.a = 0
    Protected VolSendMessageError.a = 0
    Protected TimeSendString$ = FormatDate ("%hh:%ii:%ss", Date())
    Protected TimeSendStringError$ = TimeSendString$
    Protected ValStatusByteError.a = $00
    Protected ValBytesInMessageOutError.a = 0
    Protected ValBytesInMessageRealOutError.a = 0
    Protected VolLoggerWriteOutputNoFull.a = 0

    Protected ValSendRealTime.a, MaskSendRealTime.a
    *PointerValSendRealTime = @ValSendRealTime

    Protected Dim ArrayByteSend.a(9)
    Protected TempArraySendCOM.a
    *PointerBufferSendCOM = @TempArraySendCOM
    Protected TempArrayRecieveCOM.a
    *PointerBufferRecieveCOM = @TempArrayRecieveCOM
    Protected StringSendMessage$ = ""
    Protected StringSendMessageNoFull$ = ""
    Protected TempFullString$ = ""

    Protected Dim ArrayByteSendMTC.a(7)
    Protected ModePlayMTCsend.a = 0
    Protected CounterMTSsendComment.a = 0

    Protected VolCleareLoggerProcedure.a = 0
    Protected VolLoggerOutputProcedure.a = 0



    Repeat



       If Exit = 6
           Exit = Exit + 1
         Break
       Else
       EndIf



       LockMutex (MutexMainToThreadCOM)
         VolCleareLoggerProcedure = VolCleareLogger
         VolCleareLogger = 0
         VolDrumChannelSendProced = VolDrumChannelSend
         ValDrumChannelSendProced = ValDrumChannelSend
       UnlockMutex (MutexMainToThreadCOM)

       VolCleareCounterActiveSensingProcedCOM = 0

       LockMutex(MutexIntervalSendByte)
            CounterIntervalSendByteProcedCOM = CounterIntervalSendByte
            ValIntervalSendByteProcedCOM = ValIntervalSendByte
       UnlockMutex(MutexIntervalSendByte)
            VolCleareCounterIntervalSendByteProcedCOM = 0

       LockMutex(MutexLimitTimeSend)
          CounterLimitTimeComPortSendProcedCOM = CounterLimitTimeComPortSend
       UnlockMutex(MutexLimitTimeSend)
          VolCleareCounterLimitTimeComPortSendProcedCOM = 0





        If IsSerialPort(#OpenComPort) <> 0


          If AvailableSerialPortOutput(#OpenComPort) = 0

              LockMutex (MutexRunningStatus)
                 VolRunningStatusProced = VolRunningStatus
              UnlockMutex (MutexRunningStatus)

                 VolCleareCounterLimitTimeComPortSendProcedCOM = 1


             VolSendMessage = 0




              If VolSendMessage = 1

                If VolCycleBufferComPort = 1

                     If CounterIntervalSendByteProcedCOM >= ValIntervalSendByteProcedCOM
                           VolCleareCounterIntervalSendByteProcedCOM = 1


                              If IsSerialPort(#OpenComPort) <> 0

                                If AvailableSerialPortOutput(#OpenComPort) = 0

                                   Repeat

                                          TempArraySendCOM = CycleBufferSendComPort(CounterCycleBufferSendRead)
                                            CounterCycleBufferSendRead = (CounterCycleBufferSendRead + 1) % #CounterCycleBufferSendMax
                                               If CounterCycleBufferSendRead = CounterCycleBufferSendWrite
                                                    VolCycleBufferComPort = 0
                                               Else
                                               EndIf


                                           VolWriteToComPortProced = 0
                                       If TempArraySendCOM < $F8

                                           If TempArraySendCOM >= $80

                                               LockMutex(RunningStatusLimit)
                                                  CounterStatusBytesRunningStatusLimitLow = CounterStatusBytesRunningStatusLimitLow + 1
                                                   If CounterStatusBytesRunningStatusLimitLow >= 10
                                                          If CounterStatusBytesRunningStatusLimit < 255
                                                               CounterStatusBytesRunningStatusLimit = CounterStatusBytesRunningStatusLimit + 1
                                                          Else
                                                          EndIf
                                                        CounterStatusBytesRunningStatusLimitLow = 0
                                                   Else
                                                   EndIf

                                                If VolRunningStatusProced = 1

                                                     If (TempArraySendCOM <> ArrayByteSend(0)) Or (TempArraySendCOM >= $F0 And TempArraySendCOM < $F8)
                                                          VolWriteToComPortProced = 1
                                                          CounterStatusBytesRunningStatusLimit = 0
                                                          CounterStatusBytesRunningStatusLimitLow = 0
                                                          CounterTimeRunningStatusLimit = 0
                                                     Else

                                                           If VolRunningStatusLimitYes = 0


                                                           ElseIf VolRunningStatusLimitYes = 1

                                                                   If VarRunningStatusLimit = 0

                                                                       If CounterStatusBytesRunningStatusLimit >= ValRunningStatusLimitMessage
                                                                            VolWriteToComPortProced = 1
                                                                            CounterStatusBytesRunningStatusLimit = 0
                                                                            CounterStatusBytesRunningStatusLimitLow = 0
                                                                            CounterTimeRunningStatusLimit = 0
                                                                       Else

                                                                       EndIf

                                                                   ElseIf VarRunningStatusLimit = 1

                                                                       If CounterTimeRunningStatusLimit >= ValRunningStatusLimitTime
                                                                            VolWriteToComPortProced = 1
                                                                            CounterTimeRunningStatusLimit = 0
                                                                            CounterStatusBytesRunningStatusLimit = 0
                                                                            CounterStatusBytesRunningStatusLimitLow = 0
                                                                       Else

                                                                       EndIf


                                                                   Else
                                                                      MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50004" + SetStringOutSys$ + FatalErrorMes01_01$)
                                                                      StopComPort()
                                                                      End
                                                                   EndIf

                                                           Else
                                                              MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50005" + SetStringOutSys$ + FatalErrorMes01_01$)
                                                              StopComPort()
                                                              End
                                                           EndIf


                                                     EndIf


                                                ElseIf VolRunningStatusProced = 0
                                                          VolWriteToComPortProced = 1
                                                          CounterStatusBytesRunningStatusLimit = 0
                                                          CounterStatusBytesRunningStatusLimitLow = 0
                                                          CounterTimeRunningStatusLimit = 0

                                                Else
                                                   MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50006" + SetStringOutSys$ + FatalErrorMes01_01$)
                                                   StopComPort()
                                                   End
                                                EndIf

                                               UnlockMutex(RunningStatusLimit)
                                           Else
                                                VolWriteToComPortProced = 1

                                           EndIf


;
                                       Else
                                          MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50007" + SetStringOutSys$ + FatalErrorMes01_01$)
                                          StopComPort()
                                          End
                                       EndIf


                                   Until VolWriteToComPortProced = 1 Or VolCycleBufferComPort = 0




                                   If VolWriteToComPortProced = 1

                                       If WriteSerialPortData(#OpenComPort, *PointerBufferSendCOM, 1)



                                           If TempArraySendCOM >= $80 And TempArraySendCOM < $F8
                                               If ValBytesInMessageRealOut > 0 And ValBytesInMessageRealOut < 10            ; Error
                                                    StringSendMessageError$ = StringSendMessage$
                                                    ValStatusByteError = ArrayByteSend(0)
                                                    TimeSendStringError$ = TimeSendString$
                                                    ValBytesInMessageOutError = ValBytesInMessageOut
                                                    ValBytesInMessageRealOutError = ValBytesInMessageRealOut
                                                    VolSendMessageError = 1

                                               ElseIf ValBytesInMessageRealOut = 0

                                               Else
                                                  MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50014" + SetStringOutSys$ + FatalErrorMes01_01$)
                                                  StopComPort()
                                                  End
                                               EndIf

                                                ArrayByteSend(0) = TempArraySendCOM
                                                ValBytesInMessageOut = BytesInMessage(ArrayByteSend(0))
                                                ValBytesInMessageRealOut = 1
                                                StringSendMessage$ = "  " + Hex(ArrayByteSend(0))

                                           ElseIf TempArraySendCOM < $80

                                                If ValBytesInMessageRealOut = 0
                                                      If ArrayByteSend(0) < $80 Or ArrayByteSend(0) > $F0
                                                          StringSendMessageError$ = " (" + RSet(Hex(ArrayByteSend(0)), 2, "0") + ") " + RSet(Hex(TempArraySendCOM), 2, "0")
                                                          ValStatusByteError = ArrayByteSend(0)
                                                          TimeSendStringError$ = FormatDate ("%hh:%ii:%ss", Date())
                                                          ValBytesInMessageOutError = 2
                                                          ValBytesInMessageRealOutError = 2
                                                          VolSendMessageError = 1
                                                      Else
                                                          StringSendMessage$ = " (" + RSet(Hex(ArrayByteSend(0)), 2, "0") + ") " + RSet(Hex(TempArraySendCOM), 2, "0")
                                                          ValBytesInMessageOut = BytesInMessage(ArrayByteSend(0))
                                                          ArrayByteSend(1) = TempArraySendCOM
                                                          ValBytesInMessageRealOut = 2
                                                      EndIf
                                                Else
                                                      StringSendMessage$ = StringSendMessage$ + "  " + RSet(Hex(TempArraySendCOM), 2, "0")
                                                      ArrayByteSend(ValBytesInMessageRealOut) = TempArraySendCOM
                                                      ValBytesInMessageRealOut = ValBytesInMessageRealOut + 1
                                                EndIf

                                           Else
                                              MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50008" + SetStringOutSys$ + FatalErrorMes01_01$)
                                              StopComPort()
                                              End
                                           EndIf


;
                                           If VolLoggerOutputProcedure = 1

                                                 If ValBytesInMessageRealOut = ValBytesInMessageOut

                                                       VolLoggerWriteOutputMessage = 1

                                                 ElseIf ValBytesInMessageRealOut < ValBytesInMessageOut

                                                 Else
                                                    MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50003" + SetStringOutSys$ + FatalErrorMes01_01$)
                                                    StopComPort()
                                                    End
                                                 EndIf

                                           ElseIf VolLoggerOutputProcedure = 0
                                           Else
                                              MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50016" + SetStringOutSys$ + FatalErrorMes01_01$)
                                              StopComPort()
                                              End
                                           EndIf

                                            TimeSendString$ = FormatDate ("%hh:%ii:%ss", Date())

                                              VolCleareCounterActiveSensingProcedCOM = 1

                                       Else
                                          MessageRequester(ErrorMes00$, NameComPort$ + SetStringOutSys$ + Mes_ComPortNotWrite01_00$ + " " + Mes_ComPortNotWrite01_01$)    ; Message
                                          StopComPort()
                                       EndIf
;
                                   ElseIf VolWriteToComPortProced = 0
                                   Else
                                      MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50009" + SetStringOutSys$ + FatalErrorMes01_01$)
                                      StopComPort()
                                      End
                                   EndIf

                                Else
                                   MessageRequester(ErrorMes00$, NameComPort$ + SetStringOutSys$ + Mes_ComPortNotFree01_00$ + " " + Mes_ComPortNotFree01_01$)    ; Message
                                   StopComPort()
                                EndIf

                              Else
                                 MessageRequester(ErrorMes00$, NameComPort$ + SetStringOutSys$ + Mes_ComPortNotFound01_00$ + " " + Mes_ComPortNotFound01_01$)    ; Message
                                 StopComPort()
                              EndIf

                     Else

                     EndIf


                ElseIf VolCycleBufferComPort = 0
                Else
                   MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50010" + SetStringOutSys$ + FatalErrorMes01_01$ + SetStringOutSys$ + "VolCycleBufferComPort = " + Str(VolCycleBufferComPort))
                   StopComPort()
                   End
                EndIf



            ElseIf VolSendMessage = 0
            Else
               MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50011" + SetStringOutSys$ + FatalErrorMes01_01$)
               StopComPort()
               End
            EndIf


                SignalSemaphore(SemaphoreCycleBuffer)

                SignalSemaphore(SemaphoreFullCycleBuffer)






          Else
               If CounterLimitTimeComPortSendProcedCOM < 200

               Else
                  MessageRequester(ErrorMes00$, NameComPort$ + SetStringOutSys$ + Mes_ComPortNotFree01_00$ + " " + Mes_ComPortNotFree01_01$)    ; Message
                  StopComPort()
               EndIf
          EndIf






          LockMutex(MutexTimer30ms)
            If VolCleareCounterActiveSensing = 0
                 VolCleareCounterActiveSensing = VolCleareCounterActiveSensingProcedCOM
            ElseIf VolCleareCounterActiveSensing = 1
            Else
             UnlockMutex(MutexTimer30ms)
               MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50????" + SetStringOutSys$ + FatalErrorMes01_01$)
               StopComPort()
               End
            EndIf
          UnlockMutex(MutexTimer30ms)


          If VolCleareCounterIntervalSendByteProcedCOM = 1
              LockMutex(MutexIntervalSendByte)
                CounterIntervalSendByte = 0
              UnlockMutex(MutexIntervalSendByte)
          ElseIf VolCleareCounterIntervalSendByteProcedCOM = 0
          Else
             MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:  50????" + SetStringOutSys$ + FatalErrorMes01_01$)
             StopComPort()
             End
          EndIf







        Else

             VolCleareCounterLimitTimeComPortSendProcedCOM = 1

        EndIf





        LockMutex(MutexLimitTimeSend)
           VolCleareCounterLimitTimeComPortSend = VolCleareCounterLimitTimeComPortSendProcedCOM
        UnlockMutex(MutexLimitTimeSend)







    ForEver


    FreeArray (ArrayByteSend())
    FreeArray (ArrayByteSendMTC())



EndProcedure






Procedure.a WriteDataToCycleBuffer (Array TempCreateArayP.a(1), ValueByteP.l)  ; 

    Protected TempProcedur.l = 0
    Protected TempVolWriteToCycleBuffer.a = 0

              WaitSemaphore(SemaphoreCycleBuffer)

              For TempProcedur = 0 To ValueByteP - 1

                  Repeat
                    TempVolWriteToCycleBuffer = 0

                     If CounterCycleBufferSendRead <> CounterCycleBufferSendWrite Or VolCycleBufferComPort = 0

                         CycleBufferSendComPort(CounterCycleBufferSendWrite) = TempCreateArayP(TempProcedur)
                         CounterCycleBufferSendWrite = (CounterCycleBufferSendWrite + 1) % #CounterCycleBufferSendMax
                         VolCycleBufferComPort = 1
                         SignalSemaphore(SemaphoreCycleBuffer)

                         TempVolWriteToCycleBuffer = 1

                     Else
                        SignalSemaphore(SemaphoreCycleBuffer)
                        TimeValueMemory.q = ElapsedMilliseconds()
                        Delay(100)
                              WaitSemaphore(SemaphoreFullCycleBuffer)

                            WaitSemaphore(SemaphoreCycleBuffer)

                     EndIf

                  Until TempVolWriteToCycleBuffer = 1

              Next

                SignalSemaphore(SemaphoreCycleBuffer)


EndProcedure



     Case #ButtonSendSysEx

            WaitSemaphore(SemaphoreCounterMTC)

            If OpenWindow(#Window_ProgressBar, WindowX(#Window_Main) + WindowWidth(#Window_Main)/2-#Width_WindowProgressBar/2, WindowY(#Window_Main) + WindowHeight(#Window_Main)/2-#Height_WindowProgressBar/2-80, #Width_WindowProgressBar, #Height_WindowProgressBar, WindowsProgress2$, #PB_Window_Tool, WindowID(#Window_Main))
                DisableWindow(#Window_Main,1)

               If ProgressBarGadget(#ProgressBarIndSysex, 5, 5, #Width_WindowProgressBar-10, #Height_WindowProgressBar-10, 0, SizeDumpFileOrig)
                  DisableWindow(#Window_ProgressBar,1)


                      For TempL = 0 To SizeDumpFileOrig - 1


                        If TempL & %111111111 = 0
                           SetGadgetState (#ProgressBarIndSysex, TempL)     ; Info to ProgressBar
                        Else
                        EndIf

                        If TempL & %11111 = 0
                           WindowEvent() : WindowEvent()
                           WindowEvent() : WindowEvent()
                           WindowEvent() : WindowEvent()
                           WindowEvent() : WindowEvent()
                        Else
                        EndIf

                        TempArrayCreateMidiCommand(0) = SysExDump(TempL)
                        WriteDataToCycleBuffer (TempArrayCreateMidiCommand(), 1)
                          DelayWriteBytes()


                      Next

                      SignalSemaphore(SemaphoreCounterMTC)


                      CloseWindow(#Window_ProgressBar)

                     DisableWindow(#Window_Main,0)
                     UseGadgetList(OldGadgetList)

               Else
                   MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:50????" + SetStringOutSys$ + FatalErrorMes01_01$) ; 
                   End
               EndIf

            Else                     ; Window of Status-bar
                MessageRequester(FatalError00$, FatalErrorMes01_00$  + SetStringOutSys$ + "Code:50????" + SetStringOutSys$ + FatalErrorMes01_01$) ; 
                End
            EndIf




Отредактировано Gregory (22.11.2020 20:39:35)

0

10

Gregory написал(а):

Как скажите (но только кусочек):

Как минимум непонятно где LockMutex для этих строк.

Код:
              Else
                MessageRequester(ErrorMes00$, NameComPort$ + SetStringOutSys$ + Mes_ComPortNotFound01_00$ + " " + Mes_ComPortNotFound01_01$)    ; Message
                StopComPort()
              EndIf
              
            Else
              UnlockMutex(MutexIntervalSendByte) <-------- Где LockMutex(MutexIntervalSendByte)?
            EndIf
Код:
        If CounterLimitTimeComPortSendProcedCOM < 200
          
        Else
          UnlockMutex(MutexLimitTimeSend) <-------- Где LockMutex(MutexLimitTimeSend)?
          MessageRequester(ErrorMes00$, NameComPort$ + SetStringOutSys$ + Mes_ComPortNotFree01_00$ + " " + Mes_ComPortNotFree01_01$)    ; Message
          StopComPort()
        EndIf
      EndIf

0

11

Пётр написал(а):

где

Рудименты.
Исправил. :)

0

12

Изрядно перелопатил алгоритм.
Так, вроде. работает.
Но надо ещё лог вести.
Делаю это в том же потоке (где в КОМ отправляю).
По мере накопления отправленных байтов, дешифрую посылки в текстовую строку и пишу во ListViewGadget.
Тут и происходит затык.
Т.е. если посылка была короткой (в несколько байт), и после записи в логер не надо извлекать следующие данные из буфера, то всё проходит нормально.
А вот если идёт передача большого объёма информации, то затык и получается.
Причём вставка Delay(пробовал до секунды) никак не помогает.
Убираю запись в гаджет и опять всё происходит нормально, причём те же строки нормально выводятся в дебагер.
Так вот, может всё-таки есть какие-то нюансы (например нельзя с гаджетами из потоков работать, и т.п.)?

0

13

Gregory написал(а):

например нельзя с гаджетами из потоков работать

В windows можно но будет медленно.
В линукс нельзя, т. к. GTK не поддерживает многопоточность.
Можно использовать такой метод

Код:
Enumeration #PB_Event_FirstCustomValue
  #MyEvent
EndEnumeration

Procedure SendLog(s.s)
  Protected *s.String = AllocateStructure(String)
  If *s
    *s\s = s
    If PostEvent(#MyEvent, 0, 0, 0, *s) = 0
      FreeStructure(*s)
    EndIf
  EndIf
EndProcedure

Procedure Thread(Value)
  For i = 0 To 10000
    Delay(1)
    SendLog("Строка № "+i)
  Next
EndProcedure

OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListViewGadget(0, 10, 10, 250, 120)

CreateThread(@Thread(), 0)

Repeat 
  Event = WaitWindowEvent()
  If Event = #MyEvent
    *s.String = EventData()
    If *s
      AddGadgetItem(0, -1, *s\s)
      FreeStructure(*s)
    EndIf
  EndIf
Until Event = #PB_Event_CloseWindow

Из потока окну отсылается сообщение и это во первых, не снижает скорость работы потока, а во вторых из потока нет работы с гаджетами.
Нужно учитывать что контроль отправки функцией PostEvent появился начиная с версии 5.72 и в предыдущих если не удалось поместить сообщение в очередь событий окна, об этом не узнаем и не освободим память. Размер очереди примерно 10 тысяч сообщений и может зависеть от ОС.

0

14

Пётр написал(а):

нельзя

Начинают всплывать нюансы. %-)

А по поводу мьютексов-семафоров?
Например, можно их использовать в нескольких потоках?

0

15

Gregory написал(а):

А по поводу мьютексов-семафоров?
Например, можно их использовать в нескольких потоках?

Естественно. Они для этого предназначены.
Я писал про GUI (окна, гаджеты).

0

16

Пётр написал(а):

Они для этого предназначены

Имелось ввиду, не в двух (как везде в примерах), а в трёх и более? :)

0

17

Нет ограничения на число потоков.

0

18

Если верить сообщениям дебагера, то не всё там хорошо (дебаги после строк с лок и анлок):

Код:
--5-- ??? Lock Mutex IntervalSendByte
CounterIntervalSendByte = 4
ValIntervalSendByte = 7
--2-- ??? Lock Mutex IntervalSendByte (Counter)
--2-- ??? Unlock Mutex IntervalSendByte (Counter)
--5-- ??? Unlock Mutex IntervalSendByte

0

19

Lock Mutex одного и того же мьютекса должно быть равно Unlock Mutex иначе ошибок не избежать.

0

20

Пётр написал(а):

Lock Mutex одного и того же мьютекса должно быть равно Unlock Mutex

Так никто и не сомневается. :yep:
Но, насколько я понимаю данный механизм, за каждым Локом должен следовать Анлок (того же потока), а вот два Лока и два Анлока подряд, это - нонсенс.

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Столкнулся возможно с глюком потока ?