Leaderboard
Popular Content
Showing content with the highest reputation on 12/12/18 in all areas
-
Unresponsive IDE and massive memory leaks with RIO
jbg replied to Stéphane Wierzbicki's topic in Delphi IDE and APIs
You can get rid of the failing CreateFile calls by using the attached IDEFixPack development snapshot. But you shouldn't come anywhere near the Win64 or Android compiler if it is installed. Only the Win32 compiler and IDE patches are already working (including the compiler directory cache that eliminates the unnecessary CreateFile calls). You can ignore the error messages during the splash screen that tell you that Win64 and Android patches couldn't be applied. IDEFixPackD103RegDev_not_even_alpha.7z -
The DDevExtensions 2.85 and the DFMCheck 1.6 are now available for Delphi 10.3 Rio. DDevExtensions Changelog Added: Support for Delphi 10.3 Rio Added: Use Unit dialog option “Every unit on a single line” Improved: UnitSelector Dialog in Delphi 2009 opens much faster Fixed: Structure-View search dropdown had a max height of 2 items Downloads
-
message posted to a queue not processed until application.processmessage is called
Fulgan posted a topic in OmniThreadLibrary
Hello, I have written a background task that communicate with a network-based message queue. Since the implementation makes use of SQLIte and SQLite does not like to access the same database from several threads at the same time, I serialized all access to the queue in a single thread and used the Otl message queue attached to the task to get and send the messages from the main thread (and other background threads). Messages in and out are posted into the task's "comm" property and I have a written a dedicated, thread-safe class that maintains a collections of listeners (lambda functions that are interested in a given message). Once a handler has been "triggered" it can (optionally) be removed from the list. This worked great but I encountered an issue that I can't quite find how to solve: I wanted to write a synchronous method that would post a message to the (network) queue and wait until it gets an answer or times out (because synchronous calls are easier to use for my co-workers). Yet, I don't want to block in the main loop because other messages will need to be received and handled. So, for the synchronous call, I do the following: - Create a Cancellation token. - Add a handler for the message I'm expecting. Once the message is received, the token is signaled and the handler removed from the list. - Send the "query" message to the queue. - Wait until either the token gets signaled or the timeout has elapsed. (the code is slightly more complex that this but that is the idea). My problem is that, in my first version of the code, my handler never received the reply (I could see it going through the message queue). So, I added a single call to "Application.processMessages" after sending the message out and then, suddenly, the code worked. Only, I can't understand what I'm doing wrong: the handler is added before the message is being sent and everything else is going through the tasks's comm facility. Is there any explanation about what's happening ? How can I removed that requirement to call application.processmessages ? Here is the code that I used (I cleared it up a bit): The management task is created like this (from the main thread): FTask := CreateTask( procedure(const task: IOmniTask) var locQueue: IGMQueue; // This interface represent the networked message queue system Timer: TStopWatch; AThreadmessage: TOmniMessage; Messages: IList<IGMQMessage>; // This is a generic list from Spring4d. begin locQueue := FMessageQueue.Clone; // Make a local copy of the (global) message queue to make sure we have an unconnected instance locQueue.Connect(true); // Connect to the network message queue Timer := TStopWatch.StartNew; // record when the thread starts while not Task.CancellationToken.IsSignalled and not Task.Terminated do // main thread loop begin // queue maintenance if Timer.ElapsedMilliseconds > 10000 then // every 10 seconds only begin locQueue.Maintenance(1000); Timer := TStopWatch.StartNew; // remember when the last maintenance was performed. end; // send out new messages while Task.Comm.Receive(AThreadmessage) do begin case AThreadmessage.MsgID of WM_SENDMESSAGE: begin if Supports(AThreadmessage.MsgData.AsInterface, IGMQMessage) then // IGMQMessage is an interface that abstract a single message queue message begin locQueue.Enqueue(AThreadmessage.MsgData.AsInterface as IGMQMessage); end; end; end; end; // receive all messages addressed to us if locQueue.TryDequeueAll(Messages) then begin MessageQueueRouter.RouteMessages(Messages); // route messages to handlers end; Sleep(100); end; end, 'Message queue processor') .CancelWith(FCancellationToken).Schedule; RouteMessages contains a multimap connection of message types and handlers (which are simply lambda to be called): when a message is received, all handlers that have been registered for that message type are invoked and the handler is optionally removed from the list. So, in order to perform by synchronous version, I wrote this: var AMessageType: String; Waitable: IOmniCancellationToken; ReceivedMessage: IGMQMessage; Timer: TStopWatch; begin result := nil; ReceivedMessage := nil; if IsActive then begin Waitable := CreateOmniCancellationToken; // add a handler to receive the first reply message from the queue FHandlers.Add( AMessageType, // a string that specify what message type I'm interested in TMessageHandlerData.Create( function(const Src: IGMQMessage; out reply: IGMQMessage): boolean begin // this code is called when a message of the correct type is received if not Waitable.IsSignalled then // check if there is still someone listening ReceivedMessage := Src; // copy the message Waitable.Signal; // signal that we have something result := false; // returning false will tell the handler management class to remove this handler from the list. end, Waitable // the FHandlers inplementation will check if this token is signalled and remove the handler from the queue if it is. )); // send the query message to the network message queue Ftask.Comm.Send(WM_SENDMESSAGE, SrcMessage);// SrcMessage is the source message. It will cause other applications connected to the same queue to send a message back. Application.ProcessMessages; // ---- this is what I don't get. if I don't put this call here, I don't get the message later Timer := TStopWatch.StartNew; // how long have we been waiting while (not Waitable.IsSignalled) and (Timer.ElapsedMilliseconds < TimeOut) do // loop until either we time out or we get a message back begin sleep(10); end; if Waitable.IsSignalled and (ReceivedMessage <> nil) then // cehck if we had an answer result := ReceivedMessage // yup, send it back else Waitable.Signal; // no, signal the token so the handler will know it cannot send the result back (if it is running) or the tells the FHandlers instance that it can ignore and remove the handler end; end; -
Unresponsive IDE and massive memory leaks with RIO
Stéphane Wierzbicki replied to Stéphane Wierzbicki's topic in Delphi IDE and APIs
@David Millington and @Uwe Raabe it is embarrassing IDE is (so far) no more freezing... Looks like something is screwed in current IDE implementation. @jbg many thanks for this. @John Kouraklis can you try this and tell me if this solves your issue (or not) ? -
RTTI, enumerated value and TCustomAttribute?
Stefan Glienke replied to Lars Fosdal's topic in RTL and Delphi Object Pascal
You can put attributes almost everywhere without any errors, that does not mean that they are planned to be supported in these places. -
Units design
Uwe Raabe replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
There is a beta for Rio as announced in this thread: https://en.delphipraxis.net/topic/287-mmx-for-delphi-103-rio/ Although there are still some minor glitches (e.g. using the v13 registry key than the v14 one), it seems to work quite reliable. When I find some time during the next days I will provide an official release. BTW, the Use Unit dialog of MMX allows to add predefined modules, which are just groups of unit names. Click the small wizard symbol to the right from the edit field. This is quite helpful when you have to add several units that somehow belong together and are often needed in full. -
Unresponsive IDE and massive memory leaks with RIO
pyscripter replied to Stéphane Wierzbicki's topic in Delphi IDE and APIs
@Stéphane WierzbickiJust a thought. Since many of us use Rio without facing this issue it appears likely that one of these 3rd party components and experts does not play well with Delphi Rio. An idea would be to start removing these 3rd party components and experts until the IDE becomes stable/responsive. Or work in the opposite direction. Start without any third-party items, confirm IDE works well and then add them one by one. -
Pointers are dangerous
Stefan Glienke replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
Yes, you can improve the compiler (the language) as much as that it is partially safe to access raw memory without copying it - google for: .NET Span<T> I did some experiments with it in Delphi and it improved some string parsing code that did not have to allocate new strings but also did not have to work with raw and rather unsafe PChar. See https://bitbucket.org/snippets/sglienke/7e6xoe/span - this however cannot do what the C# compiler can do with ref (ensure that it only lives on the stack to not lives longer than what it refers to and these things) plus C# has readonly ref - basically a readonly pointer. -
If you call it cyclical re-engineering cult, so then. I simply see it as a way to make things work smoothly for me. I see that time I invest here pays back pretty soon and thus is well spent, at least better than constantly lamenting over CodeInsight not working. Changing the compiler or CodeInsight itself is out of my reach and I am not going to wait for others to do so.