Jump to content

Dalija Prasnikar

Members
  • Content Count

    1098
  • Joined

  • Last visited

  • Days Won

    95

Everything posted by Dalija Prasnikar

  1. Dalija Prasnikar

    Delphi 12: The Embarcadero Gelt server could not be reached...

    Yeah... it will be replaced by another official statement. But, I guess in the meantime, the title tells part of the story.
  2. Dalija Prasnikar

    Delphi 12: The Embarcadero Gelt server could not be reached...

    https://blogs.embarcadero.com/we-are-experiencing-a-hardware-outage/
  3. Which will happen during the cleanup in TThread destructor because of fEven.SetEvent which is called in TerminatedSet. Please read everything I posted before. If you don't trust me, then run the code yourself. We are running in circles now.
  4. The TThread destructor will call all that. I suggest you look at the source code. After that inherited destructor call is finished, the background thread will no longer run and it will be safe to call fEvent.Free.
  5. I said "was possible race condition", which is fixed if you call inherited thread destructor before you call fEvent.Free.
  6. Self destructing threads, while useful, have their own issues. They cannot be terminated directly, waited for, or properly cleaned up during the application shutdown and can cause various issues and exceptions during the shutdown. Basically, you lose proper application cleanup. Actually, you can do proper cleanup with such threads, too, but only if you add plenty of code that will also have to fiddle around with Windows API, and when doing all that, you are effectively rewriting infrastructure that is already in place inside TThread class. And then you are back to the square one, where you need to handle thread cleanup in proper order, basically achieving nothing comparing to using thread class that you need to manually Free - which again will work properly, if you pay little attention.
  7. Event will be triggered when TerminatedSet is called, which will be called as part of the thread cleanup process triggered by inherited destructor. There is no undefined behavior. Thread will finish, there was only a possible race condition where fEvent could have been released while background thread was still using it.
  8. Default TThread destructor will wait for thread to finish, so there will be no undefined behavior. That is why this inherited destructor needs to run first. Otherwise, you must always wait for a thread before you call Free on it. Because it is easy to forget calling WaitFor before calling Free every time you use a thread somewhere, it is much safer to call the inherited destructor first, because that is something you need to write only once.
  9. @Remy Lebeau fEvent should be released after inherited destructor runs as thread might still be running at that time if thread is not waited for before calling Free (which is not common pattern in Delphi code) destructor TTimerThread.Destroy; begin inherited Destroy; fEvent.Free; end;
  10. Depends on the decision. Replacing Sleep with event later on is trivial. In this case we don't even know whether we need to have a thread that will sleep or wait on an even in the first place. This is the "wrong direction" I am talking about.
  11. If you know absolutely nothing about threads, then Sleep can be a first step towards solution. It will at least give you a simple proof of concept code. If you need to learn everything at once it can be overwhelming. But, again, at this point we are discussing the Sleep vs events while we don't even know if we are going in the right direction.
  12. I don't think we are at that level yet. We first even have to establish what is even remotely appropriate solution, given that the problem is vague. And then we can start optimizing the code. So Sleep() suggestion is a valid one. If Sleep could be used, then we can offer better solutions than using Sleep().
  13. It seems like you don't even need a timer in a background thread, you just want to periodically run some task in the background thread. procedure TForm2.Timer1OnTimer(Sender: TObject); begin TTask.Run( procedure begin // call here anything that needs to run in the background thread end; end; Again, it would be so much easier to give you some suggestions if you would just show some of your code.
  14. If you want the timer to run in the thread then the thread will not idle. You need to run your timer related code within the Execute method. To simplify, the Execute method is the one that runs in the background thread, thread constructor does not run in the background thread. You have some deep misconceptions about how threads work, but I cannot help you if you don't show your code. Right now you are doing everything wrong and you are not running any code in the background thread.
  15. The code within Execute method is what runs in the background thread. If you don't have any code there then you don't have a thread. If you want to run a timer in background thread, then you need to create that time in the Execute method , run a loop which handles messages and then release the times when thread terminates. There is plenty of code that needs to go in the Execute method. Background thread that is created by TThread class (at some point) will terminate when it exits the Execute method. Because there is nothing in the Execute method thread will terminate immediately when it runs. (since there is nothing there, it will On the other hand, your thread object instance will be alive until you free it. I cannot tell you more because you haven't shown any code you already have.
  16. Dalija Prasnikar

    Android: Lost access to my database files after re-install

    If you cannot access the public folder with application built with Delphi 12, and you could with application built with older Delphi, then it is probably that your application needs additional code/configuration added to the manifest, because now application runs as fully compatible with Android 13 which was introduced in Delphi 12. Older application was running in compatibility mode on Android 13 and that is why those additional requirements were not needed. I don't know what exactly you need to do as my Android applications don't require such access.
  17. Dalija Prasnikar

    Android: Lost access to my database files after re-install

    Did you deploy that application in debug mode? If you did, then the application will be signed with debug key stored in debug.keystore that is located in C:\Users\YOURUSERNAME\AppData\Roaming\Embarcadero\BDS\XX.0 where XX is the Delphi release version. For Athens that is 23.0, for Alexandria it is 22.0.... One you install your application on a phone, you always need to sign it with same key, otherwise you need to uninstall the application and install it again, but when doing so, you will lose all local files visible to that application and new application signed with different key. The similar would ahppen if you would switch between debug and release keys. Because release key is the one that matters the most, Delphi allows you to specify the location of the release keystore, but when it comes to the debug keystore, if you want to use the same one you need to manually, copy it from previous version folder into a new version folder where it will be picked up, instead of being automatically generated again. You cannot copy your files to the local application storage from the outside. If you want to do that you would have to implement import feature in your application that would be able to copy files from public folder to application local folder. There are possibly some ways to handle local application storage through adb connection, but I have never done that.
  18. Dalija Prasnikar

    VCL and VCL styles - bugs and future

    To avoid flooding another thread with unrelated posts about VCL quality and bugs, I have opened this topic for discussion about VCL in general and VCL Styles. First, I would like to respond to comment made by @Attila Kovacs VCL is not abandoned, not even close. Maybe it is not receiving too many new features as people would hope so, but it has more to do with its maturity than anything else. FMX (is) was in frenzy development cycle, only because it didn't have the needed features VCL already had, and it still does not have all. So it may have seemed that FMX is getting all the love and attention, but that was not the case. Many new Windows related features introduced since FMX has come to play, are still VCL only. Keep in mind that IDE is based on VCL, and I don't see that changing in foreseeable future. VCL is evolving and it will continue to evolve. It is not that FMX is new better, improved framework mean to replace VCL for all purposes, it is framework with completely different architecture and it covers different use cases. While some functionality certainly overlaps, and there are (Windows only) applications where both VCL and FMX can be chosen, there are also applications where VCL is far better (and sometimes, even only viable) choice. VCL Styles are buggy, they have been buggy since they were introduced in XE2. But, they are now part of the IDE. That means two things. First, IDE is now suffering from some bugs, but it also means that those bugs will get fixed sooner rather than later. Unfortunately, not all bugs can be solved overnight, and the more specific, reproducible bug reports there are, the higher are chances that those bugs will get a fix. If you have any filed VCL bug reports you might want to share, please do so.
  19. How much he earns from the Android app is not relevant. How much he earns in total is relevant. See: https://www.embarcadero.com/products/delphi/starter/faq Yes, subject to the restrictions summarize below and stated in the License Agreement. If you're an employee of a small company or organization with revenue up to $5,000 per year, you can use the Community Edition. Once the company's total revenue reaches US $5,000 per year or your team expands to more than 5 developers, you must buy an unrestricted paid commercial license. Also there are some restrictions if you already have other Delphi versions. the last thing anyone would want is receiving invoice for regular version, because they used CE edition for writing Android part of they regular Windows app developed in Delphi. Verifying that CE could be used in particular scenario is the best option.
  20. Community version has very strict requirements considering who can use it. If you are earning money with your older Delphi version, then you definitely cannot use the community edition. Even if you don't earn money with it, you may get in trouble because community edition is cannot coexist with other Delphi versions not only on the same computer, but also on the same local network. If you think you have grounds for using it, you should check with Embarcadero officials first about your particular use case to avoid potential issues.
  21. Dalija Prasnikar

    Custom managed records with String List causing memory leak

    It is very likely that you would have less issues with interface based class and then you would be able to pass around interface reference without having to worry about memory management too much. If you still want to use record, you need to fix your Clear procedure. You are calling CustomButtons.Free there which will destroy CustomButtons instance and then you would have crash in Finalize which would try to destroy that same instance. You should just clear the list and not free it there. So that memory management happens solely within Initialize and Finalize methods. procedure TTaskDialogParams.Clear; begin CustomButtons.Clear; end; class operator TTaskDialogParams.Finalize(var Dest: TTaskDialogParams); begin Dest.CustomButtons.Free; end;
  22. https://learn.microsoft.com/en-us/visualstudio/ide/ai-assisted-development-visual-studio You can use GitHub Copilot with VS Code. My current problem with those AI tools is accuracy (which is less of a problem if you know what you are doing and you are using it for small code snippets completion), potential legal issues (they trained on open source, but that does not mean that they haven't violated open source licenses), and next question is how much of my code ends up in training data which may leak security sensitive data.
  23. I am not following. What function declarations have with records and record pointers we are talking about here? You cannot separate ownership from access. The pointer no longer has the responsibility to release it, but instead of having one problem - one reference that needs to be tracked, managed and released. You now have two you need to pay attention to. Just because you only need to release one, does not mean that you can do just about anything with the other. And if you pass such pointer to the record out of scope, you have just created access violation. Once you free the wrapper object, your record pointer becomes dangling reference. I am not even going to comment about whole wrapping record into object and then working with pointer to that record instead of just using pointer and be done with it... Whether or not you would do all that depends on the context of the code you are dealing with. Wrapping object in a object or an automatically managed object could make sense, but it could also be the opposite. first you need to write such wrapper code and then you need to maintain it. Again, it could make sense in some scenarios where you want to add some additional functionality to a record you cannot otherwise change, but just for allocation it on the heap it doesn't.
  24. Well, in Delphi we commonly use phrases untyped and typed pointers. so when you say raw pointer in Delphi context my immediate association is untyped pointer, especially since your next comparison with C++ unique pointer and shared pointer which are automatically managed was completely unrelated feature to Delphi objects which are not automatically managed. So I assumed that you wanted to say untyped, as I haven't made the connection with the rest and what you are trying to say. I am still not certain what was your original point... as it seems that you were arguing for both style and memory management, otherwise why mentioning unique and shared pointer. I have chosen to disregard the automatic memory management part as this would be adding additional level of complexity and focus on the class part alone. Again, that depends on the rest of the code. In general, if you are dealing with records, then using typed pointer to that record is more consistent and idiomatic than wrapping that record into a class, just to have it allocated on the heap. Especially, since Delphi no longer requires dereferencing typed pointers when working with their content. TRec = record x: Integer; end; PRec = ^TRec; TRecObject = class public r: TRec; end; var p: PRec; begin New(p); try p.x := 5; finally Dispose(p); end; end; var o: TRecObject; begin o := TRecObject.Create; try o.r.x := 5; finally o.Free; end; end If you look at the above code, the using pointer makes code more readable than having wrapped record as you can directly access its content through pointer reference instead of having another level of indirection between.
  25. Typed pointers are quite different from raw pointers. Both class and pointer in make sense, but which one you will chose, pretty much depends on the other code in the context. Declaring a class merely for a single procedure might be an overkill. From the safety perspective typed pointers in Delphi are equally safe or unsafe as classes. You still have to manage their memory and pay attention to what you are doing with them.
×