Привет!
Есть MDI приложение, которое получает данные по DDE
Дочерних окон много (сейчас 99), но может быть и больше (около 140)
Из главного окна данные передаются в дочернее окно так:
В дочернем окне данные принимаются
OutData в главном окне и inData в дочернем окне объявлены как структура (Transfer data)
Для развязки окон используется
Все нормально работает, но достаточно медленно
Идет непрерывный поток данных по DDE, а дочерних окон много
и пока в дочернем окне не отработает процедура
Процесс раздачи данных по дочерним окнам приостанавливается
Если в дочернем окне убрать процедуру
А по PoatMessage вызвать её, то во входных данных уже появляются данные, предназначенные другому окну
Сам вопрос:
Как сделать, чтобы данные просто передались в дочернее окно, а уж потом, по PostMessage, они парсились?
Можно для каждого дочернего окна создавать отдельный поток и UpdExpertData(); запускать в отдельном потоке. PostMessage в отличии от SendMessage вроде асинхронная функция и во время ее работы основной поток не останавливается. Надо еще придумать какие то флаги сигнализирующие о том, что процесс в процессе :) обработки данных и пока он его не отработает не передавать новые данные этому окну. Если каждое дочернее окно будет работать в отдельном потоке, то тогда процесс передачи данных не будет останавливаться и ждать пока окно отработает данные, а сразу же будет передавать данные следующему окну. Слабое место всех MDI приложений, как раз в этом что все дочерние окна работают в одном потоке главного окна. Если для каждого дочернего окна предусмотреть отдельный поток то думаю проблема будет решена.
...
Вот накопал статейку на эту тему. https://www.ispras.ru/proceedings/docs/2017/29/1/isp_29_2017_1_231.pdf
Вот еще - https://habr.com/ru/post/144681/
....
Еще вопрос в процессе работы используете функцию Application.ProcessMessages?
- 2012.05.28
- habr.com
Можно для каждого дочернего окна создавать отдельный поток и UpdExpertData(); запускать в отдельном потоке. PostMessage в отличии от SendMessage вроде асинхронная функция и во время ее работы основной поток не останавливается. Надо еще придумать какие то флаги сигнализирующие о том, что процесс в процессе :) обработки данных и пока он его не отработает не передавать новые данные этому окну. Если каждое дочернее окно будет работать в отдельном потоке, то тогда процесс передачи данных не будет останавливаться и ждать пока окно отработает данные, а сразу же будет передавать данные следующему окну. Слабое место всех MDI приложений, как раз в этом что все дочерние окна работают в одном потоке главного окна. Если для каждого дочернего окна предусмотреть отдельный поток то думаю проблема будет решена.
...
Вот накопал статейку на эту тему. https://www.ispras.ru/proceedings/docs/2017/29/1/isp_29_2017_1_231.pdf
Вот еще - https://habr.com/ru/post/144681/
....
Еще вопрос в процессе работы используете функцию Application.ProcessMessages?
Спасибо, конечно, но Вы вероятно не поняли.
Дочернее окно лишь окно, в котором отображается информация, в всю работу выполняет класс
type TExpert = class FFutName: string; FSpotName: string; FFutAccaunt: string; FSpotAccaunt: string; FFXAccaunt: string; FClient: string; FTransBusy: boolean; FOrder: EntityNumber; FTransID: DWord; FExpData: TExpertData; FEHandle: THandle; FMaxValue: Double; FMinValue: Double; FTransAction: TTRansID; FStopTrading: boolean; FMemo: TMemo; FCEntLabel: TLabel; FСExitLabel: TLabel; FFutLabel: TLabel; FSpotLabel: TLabel; FMaxLabel: TLabel; FMinLabel: TLabel; FCBLabel: TLabel; FIntLabel: TLabel; FExtLabel: TLabel; FDivLabel: TLabel; FAvlLabel: TLabel; FMCntLabel: TLabel; FDeltaLabel: TLabel; FCurDivLabel: TLabel; FSettings: TExpertSettings; FFutVol: double; FSpotVol: double; FInData: TTransData; FOrderPrice: Double; FTrRes: Long; FExCode: Long; FTCode: Long; FRepMess: LPSTR; FVolume: Quantity; FaSell: Long; FMustSpotVol: double; FDllConn: boolean; FQConn: boolean; FWrongData: TWrongData; FEntEdit: TEdit; FExitEdit: TEdit; private procedure OnTick(); procedure UpdExpertData(); function CheckTime(var is_rem_order: boolean): boolean; function CalcProc(var inVal, outVal, CBuy, aDelta, Cdivs, iSell, oBuy: double): boolean; function PositionState(): POS_STATE; function GetFutInVolume(const aVol: double): double; function CheckMoney(const vol: double): double; procedure SendOrder(const dir: integer; const price: double; const qnty: double); function GetTransID(): dword; function CheckPosEqual(): double; function GetFutOutVolume(const aVol: double): double; procedure SellBuySpot(const aVol: double; const BuySell: integer); function CheckFutPrice(const aPrice: double): boolean; public constructor Create(); destructor Destroy; override; procedure OnTrade(); procedure OnError(); // procedure OnOrder(); //--- Property property FutName: string read FFutName; property SpotName: string read FSpotName; property FutAccaunt: string read FFutAccaunt; property SpotAccaunt: string read FSpotAccaunt; property FXAccaunt: string read FFXAccaunt; property Client: string read FClient; property TransBusy: boolean read FTransBusy; property Order: EntityNumber read FOrder; property TransID: DWord read FTransID; property ExpData: TExpertData read FExpData; property EHandle: THandle read FEHandle; property MaxValue: Double read FMaxValue; property MinValue: Double read FMinValue; property TransAction: TTRansID read FTransAction; property StopTrading: boolean read FStopTrading; property Memo: TMemo read FMemo; property CEntLabel: TLabel read FCEntLabel; property СExitLabel: TLabel read FСExitLabel; property FutLabel: TLabel read FFutLabel; property SpotLabel: TLabel read FSpotLabel; property MaxLabel: TLabel read FMaxLabel; property MinLabel: TLabel read FMinLabel; property CBLabel: TLabel read FCBLabel; property IntLabel: TLabel read FIntLabel; property ExtLabel: TLabel read FExtLabel; property DivLabel: TLabel read FDivLabel; property AvlLabel: TLabel read FAvlLabel; property MCntLabel: TLabel read FMCntLabel; property DeltaLabel: TLabel read FDeltaLabel; property CurDivLabel: TLabel read FCurDivLabel; property Settings: TExpertSettings read FSettings; property FutVol: double read FFutVol; property SpotVol: double read FSpotVol; property InData: TTransData read FInData; property OrderPrice: Double read FOrderPrice; property TrRes: Long read FTrRes; property ExCode: Long read FExCode; property TCode: Long read FTCode; property RepMess: LPSTR read FRepMess; property Volume: Quantity read FVolume; property aSell: Long read FaSell; property MustSpotVol: double read FMustSpotVol; property DllConn: boolean read FDllConn; property QConn: boolean read FQConn; property WrongData: TWrongData read FWrongData; property EntEdit: TEdit read FEntEdit; property ExittEdit: TEdit read FExitEdit; end;
И в этом экземпляре Класса есть переменная (FInData: TTransData) - в которую принимаются данные, а дочерняя форма служит лишь для идентификации экземпляра класса и содержит несколько функций, через которые можно обращаться
к данному экземпляру класса. Что поток запускать (кстати тоже класс), что экземпляр Класса - одно и тоже.
Спасибо, конечно, но Вы вероятно не поняли.
Дочернее окно лишь окно, в котором отображается информация, в всю работу выполняет класс
И в этом экземпляре Класса есть переменная (FInData: TTransData) - в которую принимаются данные, а дочерняя форма служит лишь для идентификации экземпляра класса и содержит несколько функций, через которые можно обращаться
к данному экземпляру класса. Что поток запускать (кстати тоже класс), что экземпляр Класса - одно и тоже.
Не одно и тоже. Почитайте что такое многопоточные приложения. Вы говорите, что во время работы функции UpdExpertData() передача данных следующему окну не происходит. Что бы этого избежать надо что бы эта функция запускалась в отдельном потоке. И эти разные потоки будут работать одновременно (параллельно). Если вы запускаете просто экземпляр класса а затем еще какой то экземпляр класса в рамках одного потока. То второй класс как бы стоит в очереди пока не отработает 1-й запущенный класс. А если каждый класс запустить как два отдельных потока то они будут выполнятся одновременно и при этом еще будет работать главный поток.
Все прекрасно работает, но функция OnData()
procedure TMDIChild.OnData; var done: boolean; begin FExpert.FinData:= TTransData(Data^); //resive data Mutex.Lock; try done:= Expert.TransBusy; //Ckeck transaction in progress finally Mutex.Unlock; end; if(done = false) then FExpert.UpdExpertData(); //Uрdate expert data end;
Исполняется достаточно долго, потому что приходится вызывать
FExpert.UpdExpertData()
иначе, (если не вызывать UpdExpertData(), когда приходит PostMessage в буфере уже данные для другого экземпляра класса.
Нет, это робот, а не кинопроектор, отображение информации на дочерней форме это не главное, главное это вычисления и команды, которые выполняет экземпляр Класса TExpert
Application.ProcessMessages не только для отображения. PostMessage это постановка сообщения в конец очереди, SendMessage это отправка сообщения без очереди. ProcessMessages как бы заставляет принудительно выполнить сообщение находящееся в очереди.
Все прекрасно работает, но функция OnData()
Исполняется достаточно долго, потому что приходится вызывать
иначе, (если не вызывать UpdExpertData(), когда приходит PostMessage в буфере уже данные для другого экземпляра класса.
Получается, что у вас поток данных не синхронизирован. PostMessage ставит в очередь оно асинхронное (как писал выше) если долго работает UpdExpertData() нужно не посылать PostMessage пока не отработает UpdExpertData(). SendMessage после отправки сообщения дожидается отработки и ждет результата , Post же просто кладет сообщение в очередь. Выше немного не правильно написал. SendMessage тоже в очередь помещает сообщение.
Получается, что у вас поток данных не синхронизирован. PostMessage ставит в очередь оно асинхронное (как писал выше) если долго работает UpdExpertData() нужно не посылать PostMessage пока не отработает UpdExpertData().
Так сейчас и реализовано,
Child.OnData(@OutData); //Send data PostMessage(Child.Expert.EHandle, WM_ON_TICK, Child.Expert.EHandle, 0); //Init OnTick
но при этом притормаживается отдача данных в другой эксперт
А нужно просто передать данные, передал и вызвал PostMessage()
А PostMessage() вызовет OnTick() к классе, который и обработает данные.
У меня не получается "обрубить" передаваемый буфер.Так сейчас и реализовано,
но при этом притормаживается отдача данных в другой эксперт
А нужно просто передать данные, передал и вызвал PostMessage()
Попробуйте смоделировать ситуацию. Вызвали Child.OnData(@OutData); он отработал дальше PostMessage поставила в очередь сообщение №1. Оно в очереди и пока еще не отработано или в процессе работы. Потом опять Child.OnData(@OutData) и следом PostMessage №2 ставится в очередь. При этом сейчас обрабатывается сообщение №1. И так далее. Нужна синхронизация.
Попробуйте смоделировать ситуацию. Вызвали Child.OnData(@OutData); он отработал дальше PostMessage поставила в очередь сообщение №1. Оно в очереди и пока еще не отработано ил в процессе работы. Потом опять Child.OnData(@OutData) и следом PostMessage №2 ставится в очередь. При этом сейчас обрабатывается сообщение №1. И так далее. Нужна синхронизация.
Вы не понимаете, что PostMessage() не ноиер 1 и номер 2 и т.д
Postmessage() посылается в конкретное окно, мало того в один из параметров заносится хендл окна
PostMessage(Child.Expert.EHandle, WM_ON_TICK, Child.Expert.EHandle, 0); //Init OnTick
Child.Expert.EHandle
Это идентификатор окна в которое посылается сообщение.
BOOL PostMessageA( [in, optional] HWND hWnd, [in] UINT Msg, [in] WPARAM wParam, [in] LPARAM lParam );
[in, optional] hWnd Type: HWND A handle to the window whose window procedure is to receive the message. The following values have special meanings.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Привет!
Есть MDI приложение, которое получает данные по DDE
Дочерних окон много (сейчас 99), но может быть и больше (около 140)
Из главного окна данные передаются в дочернее окно так:
В дочернем окне данные принимаются
OutData в главном окне и inData в дочернем окне объявлены как структура (Transfer data)
Для развязки окон используется
Все нормально работает, но достаточно медленно
Идет непрерывный поток данных по DDE, а дочерних окон много
и пока в дочернем окне не отработает процедура
Процесс раздачи данных по дочерним окнам приостанавливается
Если в дочернем окне убрать процедуру
А по PoatMessage вызвать её, то во входных данных уже появляются данные, предназначенные другому окну
Сам вопрос:
Как сделать, чтобы данные просто передались в дочернее окно, а уж потом, по PostMessage, они парсились?