purebasic.info

PureBasic forum
Текущее время: Пн дек 17, 2018 5:41 pm

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 49 ]  На страницу 1, 2, 3, 4  След.
Автор Сообщение
СообщениеДобавлено: Пт дек 25, 2015 11:28 pm 
Не в сети
доцент
Аватар пользователя

Зарегистрирован: Вт апр 29, 2014 8:26 am
Сообщений: 66
Благодарил (а): 50 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Здравствуйте. Библиотека функций работы с потоками в PuruBasic - очень интересный подраздел.
Вот и для меня, пришло время всесторонне разобраться в ней. Многообещающе выглядит близкое знакомство с ней для разработки своих алгоритмов, но перейду к делу.
Я понимаю что поток в PuruBasic - это асинхронно выполняющаяся процедура, а не отдельный защищенный процесс операционной системы, и тем не менее это даёт мне возможность, параллельно выполнению основного кода, обрабатывать "тяжелые" функции, что актуально для хорошей отзывчивости пользовательского интерфейса программы.
Так же я узнал что всякий обмен информацией основной программы с отдельным потоком почти лишен смысла и теоретически невозможно взять из потока какие либо данные, например через переменные. Но всё же есть огромное желание научиться забирать некоторые данные из выполняющегося потока, а так-же давать ему некоторые переменные во время исполнения. Знаю, это сложная и тяжелая тема для многих. Читая комментарии на эту тему на нашем форуме, мне стало понятно, что многие просто не хотят с ними связываться, и прекрасно решают свои задачи без них. Но задачи бывают разные.
Сейчас я занимаюсь разработкой клиент-серверной программки, и зациклился вот над чем. Такие функции как OpenNetworkConnection(), ReceiveNetworkData(), SendNetworkData(), и другие - это функции, которые при определённых условиях (низкая скорость интернета, неполадки сети или оборудования) - останавливают на себе выполнение программы на время пока они разрешаться. А ведь весь оконный интерфейс программы сканируется в цикле вместе со всеми этими сетевыми функциями. Вот и получается, что отклик программы пропадает. Конечно, можно просто замораживать программу и вывести сообщение типа "подождите", но я так не хочу. Поэтому первым делом начал пробовать обрабатывать некоторые функции в отдельных потоках... Они то там работают))), но толку мне от этого, как понимаете мало, забрать тот же идентификатор сети от OpenNetworkConnection() - из потока не как. А если поместить полностью весь модуль обработки сети в поток - работает как миленький, только теперь интерфейсом взаимодействовать не возможно. Пытался даже интерфейс посадить в поток....)))).... Но вернусь к теме, и сейчас подведу к главному вопросу: Есть ли хоть малейшая возможность взаимодействовать основной программы с потоками, на уровне обмена информацией? Или эти все изыскания - напрасная трата времени?
Правда единственное решение которое я сейчас нашел - это обмен информацией через файловую систему. Это до ужаса просто. Сбрасываем на диск нужные данные, переменные и.т.д. А другим потоком или основной программой, просто читаем или изменяем их. Вот и всё! Но может кто знает или подумает, как организовать это всем доступное хранилище в оперативной памяти или ещё как нибудь? Ведь подобного рода решения могут быть чрезвычайно актуальны.

_________________
PureBasic 5.40 LTS Windows x86 x64


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб дек 26, 2015 12:14 am 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11336
Благодарил (а): 4 раз.
Поблагодарили: 443 раз.
Для начала посмотри эти темы. Возможно найдешь ответы на некоторые вопросы.
viewtopic.php?f=1&t=1102
viewtopic.php?f=1&t=3769
viewtopic.php?f=1&t=4226
viewtopic.php?f=1&t=4203
viewtopic.php?f=1&t=3874

Render писал(а):
Я понимаю что поток в PuruBasic - это асинхронно выполняющаяся процедура, а не отдельный защищенный процесс операционной системы
Да, только асинхронно выполняется не только процедура потока но и все процедуры/функции вызываемые из нее.

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

Render писал(а):
Такие функции как OpenNetworkConnection(), ReceiveNetworkData(), SendNetworkData(), и другие - это функции, которые при определённых условиях (низкая скорость интернета, неполадки сети или оборудования) - останавливают на себе выполнение программы на время пока они разрешаться.
OpenNetworkConnection() в TCP режиме еще может быть (но это можно решить задав таймаут установки соединения или переведя сокет в неблокирующий режим), а вот за остальными перечисленными функциями такого не наблюдал.

Render писал(а):
только теперь интерфейсом взаимодействовать не возможно.
Для взаимодействия можно использовать например функцию PostEvent.

Render писал(а):
Есть ли хоть малейшая возможность взаимодействовать основной программы с потоками, на уровне обмена информацией?
Конечно же есть, иначе толку от потоков было мало. Но нужно следить за тем чтобы одновременно к переменным имел доступ только один поток, т. е. блокировать доступ мьютексами.

В качестве примера многопоточной программы можно посмотреть прогу в архиве (для компиляции нужна версия на ниже 5.40).
В ней поток (процедура FileThread()) читает файл и помещает данные в память, из которой другие потоки (процедура HashThread() запущенная в нескольких потоках с разными параметрами) считывают данные и вычисляют их хеш. Этих потоков столько же сколько активных хеш-функций, но не больше чем ядер процессора.


Вложения:
MultiHash_1.0.zip [476.73 KiB]
Скачиваний: 141

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)
Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб дек 26, 2015 12:42 am 
Не в сети
доцент
Аватар пользователя

Зарегистрирован: Вт апр 29, 2014 8:26 am
Сообщений: 66
Благодарил (а): 50 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Вот спасибо Пётр за информацию! Прямо как свет на голову открываются знания! Теперь будет в чем по разбираться.

_________________
PureBasic 5.40 LTS Windows x86 x64


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб дек 26, 2015 1:27 am 
Не в сети
профессор

Зарегистрирован: Вс июн 10, 2012 8:18 am
Сообщений: 1294
Благодарил (а): 60 раз.
Поблагодарили: 49 раз.
Пункты репутации: 14
Render писал(а):
Я понимаю что поток в PuruBasic - это асинхронно выполняющаяся процедура, а не отдельный защищенный процесс операционной системы

Ну это везде так.

Render писал(а):
Читая комментарии на эту тему на нашем форуме, мне стало понятно, что многие просто не хотят с ними связываться, и прекрасно решают свои задачи без них.

Да ладно? Я вообще не представляю, как без потоков можно обойтись.
Render писал(а):
единственное решение которое я сейчас нашел - это обмен информацией через файловую систему. Это до ужаса просто

:D А глобальные переменные на что?
Ну ничего, все когда-то новичками были.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб дек 26, 2015 12:18 pm 
Не в сети
доцент
Аватар пользователя

Зарегистрирован: Вт апр 29, 2014 8:26 am
Сообщений: 66
Благодарил (а): 50 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Пожалуйста приведите простые примеры ввода / вывода данных из основной программы в работающий поток.

С мьютексами - просто беда! Прочитал всю справку и даже не смог представить себе их. Справка написана так, как будто я за ранее должен понимать что такое мьютек. Пожалуйста приведите русское толкование этого слова.

Это то описание что мне доступно...
Цитата:
CreateMutex()
Синтаксис:
Mutex = CreateMutex()
Описание:
Создаёт новый объект мьютекс . Мьютекс изначально разблокирован. Главная цель функции работы с мьютексами синхронизация потоков. Эти функции не создают слишком много издержек, но они работают только внутри программы, не по всей системе. Мьютекс это объект (разновидность семафора), которым может управлять только один поток одновременно, поэтому он используется для защиты разделяемых ресурсов. Только владеющий мьютексом поток имеет доступ к данному файлу, области памяти, ...



Давайте я попробую привести простой код для примера и покажу что и как я хочу:
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Procedure Thread(*value)
  A.l
  Repeat
    A = X      ;хочу переменную "X" из основной программы постоянно считывать в переменную "А"  потока
    ;...код потока
    ;..................
    Y = A      ;для простоты пусть внутрипотоковая "А" постоянно копируется в переменную "Y", которая из основной программы
  ForEver
EndProcedure
;=========================================================================
CreateThread(@Thread(), 0)  ;Создаю и запускаю поток
If OpenConsole()  ;основная программа для теста
  X.l
  Y.l
  Repeat
    Print("Введите цифру от 1 до 9 в переменную X: ")
    X = Asc(Input())
    If X=Asc("0"): CloseConsole(): End: EndIf  ;условие выхода из программы
    Delay(100)                                 ; просто задержка
    PrintN("возвращение числа из потока " + Chr(Y));нужно умудрится получить то же число что и ввели
    PrintN("Для выхода  введите '0', или прокатите через поток следующую цифру ...")
  ForEver
EndIf



Добавьте пожалуйста в этот пример всё что нужно чтоб он работал.

_________________
PureBasic 5.40 LTS Windows x86 x64


Последний раз редактировалось Render Сб дек 26, 2015 1:12 pm, всего редактировалось 1 раз.

Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб дек 26, 2015 1:11 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11336
Благодарил (а): 4 раз.
Поблагодарили: 443 раз.
MrF писал(а):
Я вообще не представляю, как без потоков можно обойтись.
В DOSе их не было, но как-то писали программы.

Render писал(а):
приведите простые примеры ввода / вывода данных из основной программы в работающий поток.
В описании функции CreateSemaphore() есть простой пример передачи данных из дополнительного потока в основной, используя список.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Global Semaphore = CreateSemaphore()
Global Mutex     = CreateMutex()
Global NewList Queue()
 
Procedure Producer(Total)
 
  For i = 1 To Total
    Delay(Random(750) + 250)
   
    ; The queue access still needs a normal mutex lock to be thread-safe
    LockMutex(Mutex)
      LastElement(Queue())
      AddElement(Queue())
      Queue() = i
    UnlockMutex(Mutex)    
 
    ; Signal that there is a new queue element
    SignalSemaphore(Semaphore)
  Next i
   
EndProcedure
 
If CreateThread(@Producer(), 30)
 
  For i = 1 To 30  
    ; wait for one element to be available
    WaitSemaphore(Semaphore)
   
    ; display the queue state
    LockMutex(Mutex)
      Queue$ = "Queue:"
      ForEach Queue()
        Queue$ + " " + Str(Queue())
      Next Queue()
      Debug Queue$
   
      ; remove head element from the queue
      FirstElement(Queue())
      DeleteElement(Queue())
    UnlockMutex(Mutex)
   
  Next i
 
EndIf



Render писал(а):
С мьютексами - просто беда! Прочитал всю справку и даже не смог представить себе их.
Можно еще вики почитать.
https://ru.wikipedia.org/wiki/Критическая_секция
http://www.firststeps.ru/mfc/msdn/r.php?80
https://ru.wikipedia.org/wiki/Мьютекс

А если простыми словами, то захватить мьютекс (в винде, в PB это критическая секция) может только один поток. Если попытаются это сделать другие потоки когда мьютекст захвачен, они будут ждать его освобождения (повиснут в функции LockMutex()). Таким образом получается что к совместно используемым переменных (доступ к которым производится между функциями LockMutex() и UnlockMutex()) в один и тот же момент может иметь только один поток, а остальные будут ждать освобождения мьютекса чтобы попытаться его захватить.

Render писал(а):
Давайте я попробую привести простой код для примера и покажу что и как я хочу
Переменные X и, Y должны быть глобальными.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Global X.l, Y.l
 
Procedure Thread(*value)
  A.l
  Repeat
    A = X      ;Хочу переменную "X" из основной программы постоянно считывать в переменную "А"  потока
               ;...код потока
               ;.............
               ;для простоты пусть внутрипотоковая "А" постоянно копируется в переменную "Y", которая из основной программы
    Y = A
  ForEver
EndProcedure
CreateThread(@Thread(), 0)  ;Создаю и запускаю поток
If OpenConsole()            ;основная программа для теста
 
  Repeat
    Print("Введите цифру от 1 до 9 в переменную X: ")
    X = Asc(Input())
    If X=0: CloseConsole(): End: EndIf  ;условие выхода из программы
    Delay(100)                                 ; просто задержка
    PrintN("возвращение числа из потока " + Chr(Y));нужно умудрится получить то же число что и ввели
    PrintN("Для выхода  введите '0', или прокатите через поток следующую цифру ...")
  ForEver
EndIf

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

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб дек 26, 2015 7:35 pm 
Не в сети
профессор

Зарегистрирован: Вс июн 10, 2012 8:18 am
Сообщений: 1294
Благодарил (а): 60 раз.
Поблагодарили: 49 раз.
Пункты репутации: 14
Пётр писал(а):
В DOSе их не было, но как-то писали программы.

Не, написать-то можно, даже на vb6 как-то программы пишут без потоков.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб фев 27, 2016 11:11 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 56
Благодарил (а): 43 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Всем привет!
Решил присоединиться к теме с вопросом... Программа опрашивает 2 прибора через 2 COM-порта. Организовал 2 потока. В каждом потоке происходит выделение памяти, чтобы прочитать данные из порта.

*paket=AllocateMemory() ;в первом потоке
*paketM=AllocateMemory() ;во втором потоке

Вопрос такой: нужно ли использовать мьютексы в потоках при выделении памяти?


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб фев 27, 2016 11:18 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11336
Благодарил (а): 4 раз.
Поблагодарили: 443 раз.
В данном случае не нужно.

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Вс фев 28, 2016 8:47 am 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 56
Благодарил (а): 43 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Почему то часто (1 раз в несколько секунд) проскакивают ошибки (нарушается целостность принятого пакета). Раньше был один прибор (1 поток) - ошибок не было. Подключил 2-й прибор, сделал 2-й поток - стали проскакивать ошибки. Может какие-то процессы пересекаются? Посмотрите пожлста правильно ли я читаю данные.
Переменные Hcom_CI5003, Dim RX_CI5003(18), NbDataToRead_Memograph, HCom_Memograph, Dim RX_Memograph() глобальные.

1) Так читаю ответ в первом потоке (прибор 1). Период опроса прибора 1 - 10 мс.
Код:
1
2
3
4
5
6
7
8
9
 
   *paket=AllocateMemory(20)                       ;выделяем 20 байт оперативной памяти
    If ComRead(Hcom_CI5003,*paket,19)               ;читаем принятый пакет из порта в память
      For a=0 To 18                                            ;читаем побайтно пакет из памяти в массив приема
        RX_CI5003(a)=PeekC(*paket+a)
      Next a
    EndIf
    FreeMemory(*paket)                                ;освобождаем память
 


Дальше последний элемент массива RX_CI5003(18) сравнивается с контрольной суммой (целостность пакета)..

2) Так читаю ответ во втором потоке (прибор 2). Период опроса прибора 2 - 1000 мс.
Код:
1
2
3
4
5
6
7
8
9
10
11
 
    NbDataToRead_Memograph = ComInputBufferCount(HCom_Memograph)     ;узнаём сколько байт пришло в буфер
      Global Dim RX_Memograph(NbDataToRead_Memograph-1)                      ;переопределяем массив приема
      *paketM=AllocateMemory(NbDataToRead_Memograph)                         ;выделяем NbDataToRead байт оперативной памяти
      If ComRead(HCom_Memograph,*paketM,NbDataToRead_Memograph)      ;читаем принятый пакет из порта в память
        For a=0 To NbDataToRead_Memograph-1                                        ;читаем побайтно пакет из памяти в массив приема
          RX_Memograph(a)=PeekC(*paketM+a)
        Next a
      EndIf
      FreeMemory(*paketM)                                                                   ;освобождаем память
 


Дальше последний элемент массива RX_Memograph(NbDataToRead_Memograph-1 ) сравнивается с контрольной суммой (целостность пакета)..


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Вс фев 28, 2016 12:17 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11336
Благодарил (а): 4 раз.
Поблагодарили: 443 раз.
Возможно библиотека MVCOM не поддерживает многопоточность. Лучше заменить ее на SerialPort.
В настройках компилятора включена поддержка многопоточности?
Массивы RX_CI5003 и RX_Memograph не используются в других потоках?

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Вс фев 28, 2016 8:10 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 56
Благодарил (а): 43 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Ок, заменю MVCOM на SerialPort.
В настройках компилятора стоит галка "включить безопасные потоки".
Массивы RX_CI5003() и Rx_Memograph() используются только в этих потоках.

Я открываю порты с входным и выходным буфером размером 255 байт. Может в этом причина? Может надо по 1-му байту поставить? Раньше 1 байт был, и порт принимал 19 байтные пакеты. Хотел бы здесь до конца разобраться: как порт с входным буфером в 1 байт (при открытии) может принять 19 байтов?


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Ср мар 09, 2016 2:59 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 56
Благодарил (а): 43 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Привет всем! Хочу все же разобраться в текущей проблеме. Заменил MVCOM на SerialPort - проблема осталась (хоатически возникают ошибки). Дебаггером посмотрел пакеты запроса, проблема оказалась в этом. Пакеты формируются не стабильно. Запрос у меня формируется путем чтения байт из раздела данных (DataSection). Таким образом, в одном потоке формируется запрос путем чтения из раздела данных, а в другом в это время может происходить чтение данных из порта. Может здесь возникает конфликт?
Вот часть кода для прибора 1:
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
  ;Отправляем запрос
    Restore zapros_CI5003                                                   ;помещаем указатель в начало zapros для команды Read
    x.c=0                                                                    ;переменная для хранения текущего байта из zapros
    For a=0 To 11                                                            ;цикл формирования пакета и отправки его в порт (байт за байтом)
      Read.c x                                                               ;читаем "атый" байт из раздела данных zapros_CI5003 в переменную x.c
       Select a
        Case 0 To 7,9,10                                                     ;формируемые посылки будут отличаться только адресом и CRC (8 и 11 быйты соответственно)
         TX_CI5003(a)=x
        Case 8
          Select countCI5003
           Case 1
            TX_CI5003(a)=Adr1
           Case 2
            TX_CI5003(a)=Adr2
           Case 3
            TX_CI5003(a)=Adr3
          EndSelect    
        Case 11
         TX_CI5003(a)=CreateCRC_CI5003()  
       EndSelect  
      xxCI5003.c=TX_CI5003(a)  
      ;Debug xx
      WriteSerialPortData(#SerialPort_CI5003, @xxCI5003, 1)                   ;отправляем в порт "атый" байт
    Next a                                                                   ;следующий байт...
 
;Читаем ответ
    *paketCI5003=AllocateMemory(20)                                          ;выделяем 20 байт оперативной памяти RAM
    If ReadSerialPortData(#SerialPort_CI5003, *paketCI5003, 19)              ;читаем принятый пакет из порта в память RAM
      ;Debug Hex(PeekC(*paketCI5003+3))
      For a=0 To 18                                                          ;читаем побайтно пакет из памяти RAM в массив приема
        RX_CI5003(a)=PeekC(*paketCI5003+a)
      Next a
    EndIf
    FreeMemory(*paketCI5003)                                                 ;освобождаем память
 
  DataSection                                                          ;раздел данных (пакет запроса для прибора 1)
    zapros_CI5003:
   Data.c $FF, $FF, $FF, $82, $FF, $FF, $FF, $FF, $00, $01, $00, $83
  EndDataSection
 



Вот часть кода для прибора 2:
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 
;Отправляем запрос
    Restore zapros_Memograph                                             ;помещаем указатель в начало zapros для команды Read
    x.c=0                                                                 ;переменная для хранения текущего байта из zapros_Memograph
    For a=0 To 12                                                        ;цикл формирования пакета и отправки его в порт побайтно
      Read.c x
      Select a
       Case 1                                                            ;2 и 3 байты формируют адрес прибора в ASCII
        TX_Memograph(a) = Asc(Str(AdrMemograph/10))
       Case 2
        TX_Memograph(a) = Asc(Str(AdrMemograph%10))
       Case 10                                                           ;10 байт - номер канала прибора в ASCII
        TX_Memograph(a) = Asc(Str(Channel_Memograph-1))
       Case 12                                                           ;12 байт - CRC
         TX_Memograph(a)=CreateCRC_Memograph()
       Default
         TX_Memograph(a)=x
      EndSelect
      xxMemograph.c=TX_Memograph(a)  
      ;Debug Hex(xxMemograph)
      WriteSerialPortData(#SerialPort_Memograph, @xxMemograph, 1)
    Next a
 
;Читаем ответ
    NbDataToRead_Memograph = AvailableSerialPortInput(#SerialPort_Memograph)  ;узнаём сколько байт пришло в буфер порта (размер принятого пакета)
    ;Debug Str(NbDataToRead_Memograph)
   
    If NbDataToRead_Memograph>10                                         ;пакеты размером меньше 11 байт не рассматриваем
      Global Dim RX_Memograph(NbDataToRead_Memograph-1)                 ;переопределяем массив приема (автоматически обнуляется)
      *paketM=AllocateMemory(NbDataToRead_Memograph)                     ;выделяем NbDataToRead байт оперативной памяти RAM
     
      If ReadSerialPortData(#SerialPort_Memograph, *paketM, NbDataToRead_Memograph)   ;читаем принятый пакет из порта в память RAM
        ;Debug Hex(PeekC(*paketM+NbDataToRead_Memograph-1))                ;нумерация ячеек памяти идёт с 0 до NbDataToRead-1
        For a=0 To NbDataToRead_Memograph-1                              ;читаем побайтно пакет из памяти RAM в массив приема
          RX_Memograph(a)=PeekC(*paketM+a)
        Next a
      EndIf
      FreeMemory(*paketM)                                                 ;освобождаем память
 
  DataSection                                                          ;раздел данных (пакет запроса для прибора 2)
    zapros_Memograph:
   Data.c $01, $30, $31, $02, $4D, $30, $41, $4E, $4C, $47, $30, $03, $4A
  EndDataSection
 
 



Хочется разобраться, где же здесь пересечение потоков...
Спасибо за внимание! :)


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Ср мар 09, 2016 3:58 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11336
Благодарил (а): 4 раз.
Поблагодарили: 443 раз.
В один и ото же момент, может только один поток работать с Restore и Read.
Есть два варианта решение проблемы.
1. Мьютексом блокировать остальные потоки пока идет чтение в текущем.
2. Отказаться от Restore и Read, а данные из DataSection считывать по указателю на метку.
Код:
1
2
3
4
5
6
7
8
For i=0 To 11
  Debug PeekA(?zapros_CI5003+i)
Next i
 
DataSection
  zapros_CI5003:
 Data.a $FF, $FF, $FF, $82, $FF, $FF, $FF, $FF, $00, $01, $00, $83
EndDataSection


_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Ср мар 09, 2016 5:17 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 56
Благодарил (а): 43 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Пётр, спасибо тебе огромное!


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 49 ]  На страницу 1, 2, 3, 4  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB