Нужна помощь профессионального программиста - страница 2

 
prostotrader #:

Вы не понимаете, что PostMessage() не ноиер 1 и номер 2 и т.д

Postmessage() посылается в конкретное окно, мало того в один из параметров заносится хендл окна

Это идентификатор окна в которое посылается сообщение.

Да я понял. Про номера я для наглядности. Просто вы поймите что я хочу сказать. PostMessage просто ставит в очередь на обработку и дальше его не колышет что там происходит он начинает выполнять следующую строчку кода. И у вас может быть так что очередь забита и не синхронизирована с передаваемы данными. Любой тык мышкой тоже ставится в очередь окна. 

 

Видимо, для каждого дочернего окна нужно "держать" свой буфер.

 
prostotrader #:

Видимо, для каждого дочернего окна нужно "держать" свой буфер.

Попробуйте. Можно как я и писал выше организовать все через отдельные потоки. Но тогда я думаю вам нужно будет сильно переделать код. Если делать через потоки. То схема будет примерно такая. 

Пришли данные по DDE, например по акции №1 создаем поток передаем ему данные одновременно ставим флаг что данные в процессе обработки. Этот поток работает самостоятельно и ни как не влияет на другие потоки. Поток отработал флаг снимаем тем самым сообщая, что данные обработаны и мы готовы принять следующий пакет данных. Если в процессе работы этого потока пришли данные по акции №2 так же для них создаем отдельный поток. Эти потоки могут работать параллельно друг с другом одновременно обрабатывая данные по разным акциям. Таким образом можно добиться прироста производительности, особенно если процессор многоядерный. Насколько я знаю,  MDI приложение работает в одном потоке главного окна. Родительское окно просто контейнер для дочерних окон. И PostMessage ставит данные на обработку в очередь этого одного главного потока хоть вы и адресуете сообщения разным окнам они все равно извлекают сообщения из общей очереди. Если взять хотя бы для примера тот же метатрейдер. Если на каком нибудь открытом графике стоит эксперт и он подвис, то остальные открытые графики так же не откликаются ни на какие команды. Если бы эти чарты были в разных потоках, то один зависший не повлиял бы на работу других графиков.

 
Vitalii Ananev #:

Попробуйте. Можно как я и писал выше организовать все через отдельные потоки. Но тогда я думаю вам нужно будет сильно переделать код. Если делать через потоки. То схема будет примерно такая. 

Пришли данные по DDE, например по акции №1 создаем поток передаем ему данные одновременно ставим флаг что данные в процессе обработки. Этот поток работает самостоятельно и ни как не влияет на другие потоки. Поток отработал флаг снимаем тем самым сообщая, что данные обработаны и мы готовы принять следующий пакет данных. Если в процессе работы этого потока пришли данные по акции №2 так же для них создаем отдельный поток. Эти потоки могут работать параллельно друг с другом одновременно обрабатывая данные по разным акциям. Таким образом можно добиться прироста производительности, особенно если процессор многоядерный. Насколько я знаю,  MDI приложение работает в одном потоке главного окна. Родительское окно просто контейнер для дочерних окон. И PostMessage ставит данные на обработку в очередь этого одного главного потока хоть вы и адресуете сообщения разным окнам они все равно извлекают сообщения из общей очереди. 

+
Только потоки не надо создавать/удалять при каждом чихе. Нужно держать в некотором пуле и при необходимости использовать. Или на каждое окно по потоку со своей очередью событий обработки данных.
 
Aliaksandr Hryshyn #:
+
Только потоки не надо создавать/удалять при каждом чихе. Нужно держать в некотором пуле и при необходимости использовать. Или на каждое окно по потоку со своей очередью событий обработки данных.

Да, это важное замечание. Если на каждый чих создавать новый поток ни какой памяти не хватит. Можно заранее создать необходимое кол-во потоков для каждой обрабатываемой акции. Потом по завершению работы все удалить. Главное, что бы не было утечки памяти. 

 

Гораздо проще и не напрягаясь сделать для каждого дочернего окна свой буфер :)

 
prostotrader #:

Гораздо проще и не напрягаясь сделать для каждого дочернего окна свой буфер :)

:)

Это ваше детище вам и решать. Но не ждите прироста скорости обработки данных.

 
prostotrader #:

Гораздо проще и не напрягаясь сделать для каждого дочернего окна свой буфер :)

Это не улучшит ситуацию :)))

 

Спасибо всем откликнувшимся.

Переписал на потоках, но так как ранее не работал с ними, есть вопрос по удалению потока

Создаю поток с FExpert.FreeOnTerminate:= false;

Когда закрываю поток, то подаю команду Terminate и примитивно жду завершения

if(Assigned(Expert)) then
  begin
    FExpert.Terminate;
    while not Expert.Terminated do Sleep(10);
    FreeAndNil(FExpert);
  end;

  Есть ли более элегантный способ ожидания завершения потока?

Ранее никогда не использовал Sleep() и не хотелось бы использовать.

Читал, что WaitFor нельзя использовать с Sуnchronize, а я использую  Sуnchronize

 
prostotrader #:

Спасибо всем откликнувшимся.

Переписал на потоках, но так как ранее не работал с ними, есть вопрос по удалению потока

Создаю поток с FExpert.FreeOnTerminate:= false;

Когда закрываю поток, то подаю команду Terminate и примитивно жду завершения

  Есть ли более элегантный способ ожидания завершения потока?

Ранее никогда не использовал Sleep() и не хотелось бы использовать.

Читал, что WaitFor нельзя использовать с Sуnchronize, а я использую  Sуnchronize

Вроде там есть обработчик OnTerminate срабатывать должен именно тогда когда поток завершил работу. Можно вызвать метод Terminate, а в OnTerminate очищать память.

Например так FExpert.OnTerminate :=FreeAndNil();

Вам еще нужно предусмотреть завершение всех дочерних потоков при завершении главного потока.

Я могу и ошибаться, но событие  OnTerminate у потока сработает только если он закончил выполнять метод Execute поэтому нужно в этом методе проверять если Terminated равен true то тут надо решить или продолжить выполнять метод Execute или принудительно из него выйти. В общем если Terminated равен true это еще не значит, что поток закончил выполнять метод Execute.
Причина обращения: