-
Content Count
1148 -
Joined
-
Last visited
-
Days Won
106
Everything posted by Dalija Prasnikar
-
I have published initial release of NX Horizon Event Bus for Delphi as Open Source on GitHub. Features: implements the publish/subscribe pattern, decoupling publishers and subscribers events are categorized by type any Delphi type can be used as an event supports four types of event delivery: synchronous, asynchronous, synchronous in the context of the main thread, and asynchronous in the context of the main thread provides generic record and reference-counted class wrappers for easier usage and management of existing types as events simple in both implementation and usage fast full thread safety https://github.com/dalijap/nx-horizon
-
ANN: Open Source Event Bus NX Horizon
Dalija Prasnikar replied to Dalija Prasnikar's topic in Delphi Third-Party
I was already working on my event bus when I discovered DEB. I would still work on mine even if I knew about DEB sooner, because I also wrote about it in my book and I cannot reason about other people's thought process It is also published as part of book code examples, but it is a feature that deserves separate repository not tied to the book. When it comes to why DEB would not fit my purpose (if I ignore the book part), is that it has more complicated code and more features that don't necessarily bring anything of value to me (for instance, using attributes for setting subscriptions), but on the other hand have big impact on performance. My even bus also supports all types as messages, so there is additional performance boost and avoiding unnecessary memory allocations when message fits into integer or small record type. And at last, my even bus has waitable subscription, so you can wait that all dispatched messages are being fully processed. This is critical feature for more complex cleanup scenarios - yes, it can also be achieved through other means, but it is easier when it is built in feature, and I use it a lot. And the most personal reason is that my code is more compatible (similar setup and calls) with my old thread-unsafe observer framework, and I can more easily and gradually refactor old code to using new one. -
Delphi beta testing a "premium" privilege?
Dalija Prasnikar replied to Brandon Staggs's topic in Tips / Blogs / Tutorials / Videos
It is not pay to see the roadmap. There is no longer a roadmap as such. But those that participate in beta testing have a bit more information about what is coming next in immediate and for some parts the release after that sooner than it is publicly available. -
Delphi beta testing a "premium" privilege?
Dalija Prasnikar replied to Brandon Staggs's topic in Tips / Blogs / Tutorials / Videos
Don't ask me. I don't know why. -
Delphi beta testing a "premium" privilege?
Dalija Prasnikar replied to Brandon Staggs's topic in Tips / Blogs / Tutorials / Videos
Because their marketing database is not connected to customer database. -
Delphi beta testing a "premium" privilege?
Dalija Prasnikar replied to Brandon Staggs's topic in Tips / Blogs / Tutorials / Videos
Currently one of the greatest is that when it chokes on something it needs to be killed and restarted. This can be done more easily by creating menu item in IDE. See https://stackoverflow.com/q/74164165/4267244 -
Delphi beta testing a "premium" privilege?
Dalija Prasnikar replied to Brandon Staggs's topic in Tips / Blogs / Tutorials / Videos
Trust me. Number of people testing is the least problem right now. One of the issues with LSP is that it is a huge endeavor. Which on its own would be such an issue if they could have left the old one running beside it like in Sydney. However, old tech interfering with LSP integration and they had to remove it. -
Delphi beta testing a "premium" privilege?
Dalija Prasnikar replied to Brandon Staggs's topic in Tips / Blogs / Tutorials / Videos
It seems like Premium subscription gives you "advanced" beta access. For Standard it says there is access to beta for each major version release. So reading between the lines and knowing that current beta is just an update, this might mean that only Premium subscribers will have access to this beta. https://www.embarcadero.com/support -
Then the problem is not in this particular code but all the other code that consumes all available memory. The general advice for reducing memory footprint I gave earlier still stand. Yes, using separate applications will help because each will have its own memory limit if they are running on 64-bit OS.
-
The question is whether or not you have done that correctly. The moment you write the data to file, you need to release memory of all the temporary data that was used in that process before you try to load that into control. MyMemStream := ProjectsFDTable.CreateBlobStream(ProjectsFDTable.FieldByName('Description'),bmRead); try TMemoryStream(MyMemStream).SaveToFile('t.txt'); // using absolute path is preferred finally MyMemStream.Free; end; Memo1.BeginUpdate; try Memo1.LoadFromFile('t.txt'); finally Memo1.EndUpdate; end;
-
Don't use memory stream to load data to rich edit. Create temporary file and write the data into that file and then load the data from the filestream. However, no matter what you do, at some point you will run into memory issues with 32-bit application if your application consumes a lot of memory. I suggest you switch to 64-bit. If you cannot switch to 64-bit, then the only other option is optimizing other parts of your application to reduce overall memory usage. First step for optimizing would be getting rid of all memory leaks - they can cause fragmentation which can be a huge problem. Next, reducing total memory allocation, by releasing anything that is not used at the time. Be careful with creating local components that have owner which you don't explicitly free. They will not show as memory leaks, but every time you call such method your memory consumption will increase. If that does not help, then you can try reducing memory load by avoiding default string type which is Unicode since D2009 (you haven't said which Delphi version you use) and use UTF-8 encoded strings - UTF8String and convert to Unicode only when you need to display data to the user - this is really the last option as you may need to write a lot of supporting code to avoid accidental conversions to and from Unicode strings as they will slow your application down and use extra memory in the process.
-
Detect when/what makes a tcomponet descendent is made NIL?
Dalija Prasnikar replied to alogrep's topic in VCL
What is main? You are most likely corrupting a memory by accessing same data from main thread and background thread. Also you shouldn't work with any visual control from the background thread without calling the TThread.Synchronize or TThread.Queue Also you are working with pointers, so it is possible that you are accidentally overwriting something. -
Detect when/what makes a tcomponet descendent is made NIL?
Dalija Prasnikar replied to alogrep's topic in VCL
There is a thread involved. Most likely not all data that needs to be protected is protected and another thread is either releasing the object while it is still in use, or there is memory corruption because multiple threads are messing with the data. But there is not enough code to pinpoint the problem. -
I just looked at that code and the problem is not in the inline variable. Casting as interface creates hidden interface reference no matter what and that reference hinders release. This behavior is not a regression and it is not related to inline variables so I wouldn't hope it will be fixed soon. Reported as https://quality.embarcadero.com/browse/RSP-40166
-
I suppose you tested those outside the main code block. Have you filed QP report?
-
Create multiple instances of tApplication with multiple MainThreads?
Dalija Prasnikar replied to microtronx's topic in VCL
It is complicated... In theory you can have Windows application that has multiple GUI threads with each one holding own windows message loop. The answer is no, because VCL is build on the premise of single main (GUI) thread (like many other frameworks as there is really no advantage of having such multithreaded GUI) and you would have to write your own framework to achieve such application and probably would have to rewrite significant parts of the RTL. -
Create multiple instances of tApplication with multiple MainThreads?
Dalija Prasnikar replied to microtronx's topic in VCL
No. -
ANN: Open Source Event Bus NX Horizon
Dalija Prasnikar replied to Dalija Prasnikar's topic in Delphi Third-Party
I have no idea how similar it is to Spring Events as I never used them. -
ANN: Open Source Event Bus NX Horizon
Dalija Prasnikar replied to Dalija Prasnikar's topic in Delphi Third-Party
Here is simple example: Declare event in some independent unit C type TMyEvent = type string; Unit A procedure TFormA.ButtonClick(Sender: TObject); begin NxHorizon.Instance.Post<TMyEvent>('New Caption'); end; Unit B type TFormB = class(... procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); protected fMyEventSubcription: INxEventSubscription; procedure OnMyEvent(const aEvent: TMyEvent); end; procedure TFormB.FormCreate(Sender: TObject); begin fMyEventSubcription: := NxHorizon.Instance.Subscribe<TMyEvent>(MainAsync, OnMyEvent); end; procedure TFormB.FormDestroy(Sender: TObject); begin if Assigned(fMyEventSubscription) then NxHorizon.Instance.Unsubscribe(fMyEventSubscription); end; procedure TFormB.OnMyEvent(const aEvent: TMyEvent); begin Label.Caption := aEvent; end; Since you are working with GUI, events should be dispatched either as MainAsync or MainSync and that will ensure they run in the context of the main thread. Also, because they run on the main thread, you can just unsubscribe and you don't need to WaitFor subscription to finish work as there will be no active work done in the background threads. I have put subscribing and unsubscribing in FormCreate and FormDestroy event handlers, but you can also put them anywhere else where you are doing form initialization or finalization. Or, you can subscribe and unsubscribe at some other point. -
It just needs few tweaks. First, you don't need Application.ProcessMessages anywhere - they have been commented out, but the whole point of threads is getting rid of those. So you can just forget about it 🙂 Next, this will work fine, but in case user closes the dialog before download completes already queued synchronization methods will access released form and crash. To prevent that, you need to add additional filed in Form declaration and OnCloseQuery event handler on the form. I also fixed try finally block inside thread as constructing HTTP instance can also fail (not likely event, but still), and in that case the cleanup was not proper one. I also added try..except block to show error message in case of failure. If the whole application is closed then anonymous threads can be killed at any time. If this is a possibility, then you might want to replace TThread.CreateAnyonymousThread with TTask.Run (without Start) from System.Threading as all running tasks will be waited for on application shutdown. FileDownload.pas FileDownload.dfm
-
You can find simple demo how to use threads with Indy here: https://github.com/dalijap/code-delphi-thread-safety/tree/master/Part3/19 Indy This demo is using anonymous thread, but you can also use regular threads or TTask from Parallel Programming library, too. If you can post your code I can give you more detailed advice.
-
Uh.... this is such far fetched speed optimization that it is not even worth thinking about. And if you start measuring particular solutions, you may easily find that you will not get very far with them.
-
Memory management has nothing to do with number of parameters in constructors. There are other reasons why having too many parameters is considered "bad", but those are all in line that having too many parameters can be indication that your class is doing too much - violates Single Responsibility Principle. In real life, having classes and functions that require a lot of parameters and that are not in violation of SRP, nor can be adequately split, are quite common, and often workarounds for solving such "issues" are more convoluted than having few parameters over the top. If there is really a need to have class fully initialized during construction and too many parameters poses an issue that cannot be meaningfully solved by splitting the class, then Builder pattern can be suitable solution. There is usually a lot of repetitive code involved in writing a Builder class, so it is useful only if you need to construct particular class in plenty of places across your application. The main problem with many parameters, especially when they are of same type, is that you can easily pass the wrong data to wrong parameter. This could be solved on IDE level, by showing names of the parameters as hints within code - not visible outside the IDE,, so calling the constructor or function would look like TPerson.Create(AFirstName: 'John', ALastName: 'Doe'); Another similar feature on language level are named parameters, where you can or must explicitly write parameter name in the code, similar to the above.
-
Implementation section where your TTracksAddEditForm class is declared. Just like with any other method that is declared in a class, its implementation must be included inside that unit implementation section.
-
Oops... I forgot to copy-paste that part of the code... constructor TTracksAddEditForm.Create(AOwner: TComponent; const AsMode: string; AiAlbum: integer; const AsTrack: string); begin inherited Create(AOwner); FsMode := AsMode; FiAlbum := AiAlbum; FsTrack := AsTrack; end;