Kenneth Posted June 17, 2020 Posted June 17, 2020 Всем привет! Может кто сталкивался. Решил использовать UniDac вместо FireDac, вроде все хорошо работает, но единственное, не работает UniAlerter, вроде ивентсы указал, авторегистер = тру, посылаю сообщение, тишина. И главное на десктопном приложении все работает как надо, а вот в uniGui не хочет. И еще после закрытия сервера выводит ошибку Видать все таки приходят сообщения, но не обрабатываются. Если сообщений не посылать, то этой ошибки нет. P.S. Сервер Firebird 3.0 Quote
x11 Posted June 17, 2020 Posted June 17, 2020 На всякий случай напишу, что DevArt UniDAC к uniGUI никакого отношения не имеет. Quote
Kenneth Posted June 17, 2020 Author Posted June 17, 2020 Уважаемый @x11 вы только заголовки читаете? Что значит ничего общего не имеет? Все что нужно я написал в вопросе и думаю там все понятно описано о моей проблеме. Quote
Sherzod Posted June 18, 2020 Posted June 18, 2020 Мне кажется, Вы неправильно поняли ) Он имел в виду - название Uni... Quote
x11 Posted June 18, 2020 Posted June 18, 2020 10 hours ago, Kenneth said: вы только заголовки читаете? Я просто не понимаю, почему DevArt UniAlerter должен работать в приложении uniGUI в браузере? DevArt UniAlerter - это VCL. А VCL - это не uniGUI. Если я не прав, поясните, пожалуйста. Возможно, что сообщения от DevArt UniAlerter можно как-то перехватывать и показывать сообщения средствами uniGUI? Quote
Kenneth Posted June 18, 2020 Author Posted June 18, 2020 А что ему мешает не работать? FireDac работает, FibPlus работает, так почему бы UniDacу не рабоать? DevArt UniAlerter - это не VCL, это один из компонентов для работы с базами данных. Если слышали что-нибудь про линейку компонентов FireDac, которая присутствует в комплекте с IDE дельфи, то это такой же аналог. В FireDac есть TFDEventsAlerter, так вот он работает с UniGui, но uniAlerter не реагирует. Хотя если делаю все тоже самое в обычном десктопном приложении он отзывается. Я не претендую на то чтобы разработчики UniGui занимались этим вопросом, но тем не менее, может кто то сталкивался с таким и мог бы подсказать, что не так с этим Алертом? Quote
zilav Posted June 22, 2020 Posted June 22, 2020 Да и надо понимать что использование алертов практически автоматом подразумевает начало использования вебсокетов Хотя на форуме есть очень приличный и что самое приятное рабочий код работы с вебсокетами. У меня на нем сделано автообновление датасетов у клиентов. Quote
stas Posted June 22, 2020 Posted June 22, 2020 Есть опасения, что алертер выполняется в отдельном потоке, потому, там могут быть неприятности, посмотрите код, и попытайтесь переписать так чтобы выполнять в том же потоке. Я помню делал алертер, независящий от библиотеки З.ы. zilav, спасибо, что меня помните. Quote
Kenneth Posted June 22, 2020 Author Posted June 22, 2020 @zilav, @stas спасибо вам за советы, не могли бы еще скинуть ссылку на рабочий код работы с вебсокетами? Поиск по форуму не дал результатов У меня тоже стоит задача обновлять датасеты. Quote
zilav Posted June 22, 2020 Posted June 22, 2020 Сразу примерно расскажу как сделано у меня. В основе лежит эхо-сервис с броадкаст рассылкой сообщений. Само сообщение представляет собой посути json, в котором указано что и как обновилось в системе. Клиент ловит такое сообщение и уже сам решает как он хочет отреагировать на это сообщение. Quote
Kenneth Posted June 22, 2020 Author Posted June 22, 2020 @zilav спасибо. Но почему так сложно, это по сути придется дополнительный сервис поднимать ради этого, ведь сам компонент уже предполагает в себе все эти функции. Все это конечно можно сделать, но как то усложняет систему, тогда мне было бы проще взять тот же компонент с FIBов или FireDac и уже его прикрутить. У них то это все работает. Хотя не проверял на сколько стабильно, может действительно где то в недрах есть проблемы. Но в любом случае, неужели нет возможности использовать стандартный компонент(UniAlerter)? Хотелось бы услышать мнение насколько это оправдано создавать для этого отдельный сервис, а не возиться с настройками UniAlerter или ему подобных компонентов? Quote
zilav Posted June 22, 2020 Posted June 22, 2020 Тут вообще зависит от тебя, данные кто обновляет, посути ты, ну так и что тебе мешает уведомить остальных пользователей что ты что-то поменял без каких-то алертов? unidac ходил в исходниках, посмотри что у него там внутри. Да скорее всего придется посидеть с отладчиком. Просто чем хороши вебсокеты это тем что с помощью них ты вообще можешь организовать полноценную связь между клиентами не используя БД. Хочешь чат встроить в программу, пожалуйста, надо сообщение от одного пользователя другому послать, не вопрос, надо уведомить всех о том что я что-то меняю и им возможно есть смысл обновить информацию на экране, да на здоровье. Спектр применения весьма широк. Quote
stas Posted June 22, 2020 Posted June 22, 2020 Кеннет, я вообще, не понимаю, что Вас пугает? Дополнительный сервис , как предложил zilav, убирает у Вас привязку к бд, это ли не плюс. Далее, я не видел исходников унидака, но более чем уверен, что проблема с потоками. У Вас есть два варианта, переписать унидак на внепотоковый вариант, или использовать вебсокеты. Спасибо. Quote
zilav Posted June 22, 2020 Posted June 22, 2020 помимо убирания привязки к БД получаем и плюсы, уведомления не только о событиях в БД а вообще любые, ну и уведомления идут в практически моментально что тоже весьма приятно Плюс если очень хочется то можно вообще воткнуть единый websocket сервер на все свои проекты, только в сообщения надо будет добавить какой-нибудь ID программы и версии, ну а дальше уже в унигуи проекте разрулить твоему приложению сообщение адресовано или нет Quote
Kenneth Posted June 23, 2020 Author Posted June 23, 2020 @stas, @zilav спасибо что уделили время и так подробно ответили. Я все понял, моя проблема, что немного узко мыслил. Мне то всего лишь надо было обновлять датасеты, раньше это делалось в пару действий, а тут как то внутренне не принималось, что еще что то нужно делать. Ну раз уж такие возможности открываются, думаю нужно освоить и это. Помню еще в 2008 через сокеты имел дело с примером чата внутри сети. Всем Спасибо. Quote
Kenneth Posted August 7, 2020 Author Posted August 7, 2020 @stas спасибо за пример. Но сейчас столкнулся с одной проблемой. Клиенты могут отправлять друг другу сообщения со своих сессий, здесь проблем нет, но вот никак не могу отправить сообщение с СерверМодуля. Если кидаю компонент TUniWebSocket на СерверМодуль, то при запуске вылетает с ошибкой. Каким образом можно отправить сообщение именно с СерверМодуля, у меня основные изменения с базой происходят именно здесь. П.С. Все разобрался: UniServerModule.BroadCast(nil, 'Сообщение'); Quote
Kenneth Posted August 19, 2020 Author Posted August 19, 2020 Всем доброго дня! Вот решил в своем проекте вебсокеты использовать, и возникли еще вопросы. Я получаю информацию об изменении таблицы в ServerModule, и там же пытаюсь сообщить всем (взято с примера): procedure TUniServerModule.BroadCast(AContext: TIdContext; AMsg: String); var AC: TIdContext; L:TList; i:integer; begin L:=Srv.Contexts.LockList; try for i := 0 to L.Count - 1 do begin AC := L[i]; SendSocketMessage(AC,AMsg); end; finally Srv.Contexts.UnlockList; end; end; Но проблема в том, что он всем сокетам подряд отправляет. А мне нужно только тем у кого открыта сессия в данный момент. Можно ли как то через TIdContext узнать висит ли на нем активная сессия или нет? Или как то добраться до сессии. Если нет сиссий, то я бы не отправлял на него сообщение. Quote
Kenneth Posted August 21, 2020 Author Posted August 21, 2020 Все вопрос решен! Разобрался. Если кто из знатоков читает, прошу еще совета или подсказки. Можно ли обычное десктопное приложение привязать к числу получающих уведомление от СерверМодуля? Кидал на форму TUniWebSocket и прописывал адрес url, ставлю актив, все как в вэб приложении, но ничего не происходит, он не коннектится к серверу. Есть ли какие у кого мысли по этому поводу. Задача стоит получать уведомления с сервера на десктопном VCL приложении. Quote
stas Posted August 22, 2020 Posted August 22, 2020 https://github.com/andremussche/DelphiWebsockets Quote
Skyp Posted January 23, 2023 Posted January 23, 2023 Если кому-то актуально. Fix по UniDac Alerter (для Postgres): В модуль PgClassesUni.pas в часть uses добавляем модуль: unit PgClassesUni; interface uses system.generics.collections, Находим класс TPgSQLNotificationsHandler(PgClassesUni.pas): TPgSQLNotificationsHandler = class private FBaseConnection: TPgSQLConnection; FConnection: TPgSQLConnection; FEvents: array of TEventInfo; FThread: TPgSQLNotificationsThread; FMainTH: TThread; /// добавляем строчку В этом-же классе процедуру: DoOnNotification Переносим на уровень public (декларативная часть) Ниже описываем класс потока: TMaintThread = class(TThread) strict private FQueue: TQueue<TPgSQLNotification>; FObj: TPgSQLNotificationsHandler; public procedure Execute; override; property Queue: TQueue<TPgSQLNotification> read FQueue write FQueue; property Obj: TPgSQLNotificationsHandler read FObj write FObj; end; В тело Execute пишем: { TMaintThread } procedure TMaintThread.Execute; var li: integer; le: TPgSQLNotification; begin FreeOnTerminate := True; while not Terminated do begin sleep(100); if Assigned(FQueue) and Assigned(Obj) then begin for li := FQueue.Count - 1 downto 0 do begin le := FQueue.extract; Obj.DoOnNotification(le.PID, le.Name, le.Message); le.free; le:=nil; end; end; end; if Assigned(FQueue) then FreeAndNil(FQueue); Obj := nil; end; В Destroy добавляем : if assigned(FMainTH) then FreeAndNil(FMainTH); Находим в этом же модуле процедуру: procedure TPgSQLNotificationsHandler.ProcessNotification(const Name: string; const PID: integer; const Message: string); Заменяем: Notif := TPgSQLNotification.Create; Notif.PID := PID; Notif.Name := Name; Notif.Message := Message; {$IFDEF MSWINDOWS} PostMessage(hUtilWindow, WM_NOTIFICATION, wParam(GCHandle), lParam(AllocGCHandle(Notif))); {$ELSE} try FLastNotification := Notif; FThread.Synchronize(DoNotification); finally FLastNotification := nil; Notif.Free; end; {$ENDIF} На вот это: FLastNotification := TPgSQLNotification.Create; FLastNotification.PID := PID; FLastNotification.Name := name; FLastNotification.Message := Message; if not Assigned(FMainTH) then begin FMainTH := TMaintThread.Create(True); TMaintThread(FMainTH).Obj := Self; end; if not Assigned(TMaintThread(FMainTH).Queue) then TMaintThread(FMainTH).Queue := TQueue<TPgSQLNotification>.Create; TMaintThread(FMainTH).Queue.Enqueue(FLastNotification); FLastNotification := nil; if not FMainTH.Started then FMainTH.Start; Наслаждаемся - все работает. Причиной ошибки является вызов метода Synchronyze который фризит unigui сервер (ошибка возникает), этот метод нужен на случай если придёт большое кол-во сообщений (Synchronize - будет дожидаться основной отработки). В фиксе все сообщения отработают по очереди. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.