Jump to content

Dalija Prasnikar

Members
  • Content Count

    1061
  • Joined

  • Last visited

  • Days Won

    91

Everything posted by Dalija Prasnikar

  1. Dalija Prasnikar

    Determining why Delphi App Hangs

    The code where you call Application.ProcessMessages procedure TMainForm.BtnClick1(Sender: TObject); begin DoFoo; DoBar; DoFork; end; procedure TMainForm.BtnClick2(Sender: TObject); begin DoFoo; Application.ProcessMessages; DoBar; Application.ProcessMessages; DoFork; end; procedure TMainForm.BtnClick3(Sender: TObject); begin TThread.CreateAnonymousThread( procedure begin DoFoo; DoBar; DoFork; end).Start; end; Problem with Application.ProcessMessages is that code that would execute in one block without interruptions, like in first example, can now be interrupted and some other code can start running in the middle of it. For instance you can click same button twice. Or you can close form and destroy it while other code is still running and using it. Now moving in background thread does not solve those issues, because you can still click the button twice and you can close the form while you running something in the background. But, there are few things to consider here. First, while code with ApplicationProcessMessages can be interrupted at any point, code in background thread will run serially, one line after the other, just like the code that does not call Application.ProcessMessages. It is far easier to follow the logic (and debug) such code. One of the arguments for Application.ProcessMessages was that it is easy to use, comparing to multithreading. That is true only on the surface, it seems easy and that is why we were all using it. So you have beginner developer writing all kind of poor code in event handlers and application becomes unresponsive, so he is advised to use ApplicationProcessMessages, and he sprinkles his code with those and application might work better (seemingly). In the reality, he learned nothing, his code is really bad, and sooner or later when some user clicks something unexpected everything will fall apart. When you have to move code to the background thread, you need to think more about it and you need to isolate it better. Mere process of isolating functionality will make that code better. Now, you can still have developer that will just move the whole thing to the background without doing any of that, but that code will not seemingly work (that rarely happens) and it will not work properly, which will hopefully trigger the developer to ask for help and learn how to do that properly. There is a difference. If the UI reacts slowly that means when you drag the window and it will not drag smoothly, when you click the button you may not get immediate response, so you will click it again. Background thread does not block the UI so it does not matter how long it takes to cancel the operation. You can write your code in such manner that when action is canceled, user can immediately continue doing something else. You don't have to move data between threads - data is not contained within threads (unless you specifically create thread local data), you just need to prevent multiple threads changing the same data simultaneously.
  2. Dalija Prasnikar

    Determining why Delphi App Hangs

    First, as we all know (I hope) if application cannot process messages, it becomes unresponsive and OS (and user) can kill it, because it may look like it is dead. Application.ProcessMessages pumps the message queue so the OS can see that application is still alive. There are few problems with that approach. Most obvious problem is that such code becomes re-entrant. That can cause some nasty side-effects depending on the code you are executing. But main issue is that you are still running slow operation in main thread, and no matter how much you are able to interrupt that execution with calls to Application.ProcessMessages, this will still slow down UI processing and application may respond to user input slowly. Also, this is not just the problem with reacting to input, but all the calls to Application.ProcessMessages will make that long operation running even longer. Next issue that is often overlooked is that some parts of the long running process may not always execute fast enough. Imagine connecting to some web service and retrieving some very small amount of data. In perfect conditions that may take blink of an eye, but if connection is bad for any reason, this operation can block the main thread for much longer. And Application.ProcessMessages will not help you with that. Also, for cross-platform development, this is more important because mobile devices will kill non responsive application much faster. On Android you cannot even freely perform network operations in the context of the main thread because OS will thow exception if you try. Also on android Application.ProcessMessages no longer works and can deadlock the application.
  3. Yep, I figured that out... I was still low on coffee when I took a peek at that code.
  4. Dalija Prasnikar

    Determining why Delphi App Hangs

    It seems that everything is running in main thread... so nothing really hands besides application UI.
  5. Dalija Prasnikar

    Determining why Delphi App Hangs

    This is bad idea. First, Application.ProcessMessages has some global side effects that can bite you in behind when you least expect them. Next, depending on the code, it is possible that some pieces still take too long to keep UI fully responsive. Using background threads for simple operations is not rocket science and at the end when you take all pros and cons it is not more complicated than using Application.ProcessMessages.
  6. Dalija Prasnikar

    Determining why Delphi App Hangs

    Yes, there is. But without code it is impossible to say for sure. I am guessing that you are doing all that in main thread.
  7. Not really... it accepts PTypeInfo not object instance
  8. Dalija Prasnikar

    Delphi WAT of the day

    That is useful if you get paid by the LOC compiler generates-
  9. There is another overload that takes Pointer... and it seems like this one is supposed to work with object instances, but it crashes instead.
  10. It does not fail on private fields, but on retrieving type. You are passing object and GetType expects class GetType(AnObject.ClassType)
  11. Delphi strings are pretty good as far as performance is concerned, TStringBuilder might have advantage when you need to handle longer strings and where benefits of preallocating buffer will outweigh the cost of the builder allocation, deallocation and try...finally block. I use TStringBuilder in few places, where it simplifies code, and I never measured the speed because it was not important in there. If you want to knock yourself out with micro-optimizations, you should definitely take a look at Knuth-Morris-Pratt algorithm, especially if you are matching same patterns over and over again https://en.wikipedia.org/wiki/Knuth–Morris–Pratt_algorithm
  12. It seems that TStringBuilder is not quite as fast as it could be. I didn't gave it closer look, so I cannot say whether the issue is creating and destroying TStringBuilder or other TStringBuilder code.
  13. Initial idea that multiple scans are bad for performance is good, but your steps are wrong. You should scan the string for all substrings in one go, but you should also build new string while you are scanning. Using TStringBuilder or similar pattern with preallocated buffer would be appropriate. And when I sad scanning string for substrings, don't use Pos function. Scan string one character at the time and match it with patterns you are looking.
  14. Dalija Prasnikar

    Upgrade 10.3 to 10.4

    You don't need to uninstall 10.3 or older versions. 10.4 can coexist with them. Installer will probably recognize your existing license. And ask you if you want to use it. If it does not recognize it, they it will ask you for serial number and you will need to go through online activation process.
  15. Dalija Prasnikar

    Waiting for multiple threads

    I am sorry if I misunderstood your point. You didn't explicitly said why are you suggesting passing TEvent instead of using global access and phrase "Don't forget" can be easily interpreted that if you use global objects directly, code will not work properly. At least that is how I have read it.
  16. Dalija Prasnikar

    Waiting for multiple threads

    Not using global vars is good advice, but your particular advice here is wrong for several reasons. First, accessing global state (and changing it) is always a problem when it comes to thread safety, because one thread can change that state and interfere with the other using that same state. Think of global TFormatSettings variable. Having formatting functions that works directly with global setting is not thread safe because different threads can change settings as they please. On the other hands functions that use format settings passed as parameter are safe. But the crucial thing here is not passing as parameter alone, but what happens when you pass it in this particular case. TFormatSettings is a record and when you pass it as parameter function will get a local copy of the whole record. That is what it makes it safe. When you pass object instance as parameter, function will not get local copy of the object, just the reference. If the object is not thread safe and does not implement thread safety (synchronization) mechanisms that would allow safe access from multiple threads, then using parameter or global object directly is equally bad, and will not work. However, when it comes to synchronization objects, including TEvent, their whole purpose is to be shared between multiple threads. And if you need to orchestrate threads on application level, the only way you can do that is through global object. Yes, you can still write code in such manner that it does not access global object directly, but that code will not be "more thread safe", but more flexible and allows you to pass different TEvent instances to different threads that may have different purpose and possible different synchronization events. Using global locks, events and other synchronization objects is perfectly fine.
  17. Dalija Prasnikar

    community.embarcadero.com's forums

    NNTP forums were the only ones that were really used. They were not shut down and deleted on a whim, but because of software and database problems. Posts were purged in attempts to stabilize and salvage the forums, but failures keep happening. During that time Embarcadero created new web only forums, but they were never extensively used - I am not going to analyze why.... Well, now you have Delphi Praxis for that. Old forums as such may be lost, but community is not. Many people are here and that is all that matters.
  18. I just had to do it... Go with the flow! It's the Black Friday / Cyber Monday "season", so I had to rush the book offer The book was actually scheduled for release in early December, but then the Black Friday deals started popping up all over the place... pressure was building... and I finally caved in! I cut the darn thing in two, and decided to offer Part I at a discount, and will give Part II for free to all Buyers. Not really a 97% BF discount but hey... Junior is still studying, and we still have to pay the bills (Corona doesn't help, either)! So, here it is! I hope you'll like it like you did Delphi Memory Management! https://dalija.prasnikar.info/delphiebap/index.html Thank you all for the support!
  19. Dalija Prasnikar

    Recursion in a multi-threaded program

    Depends on the algorithm. Also, to use parallel for you will need to rewrite that algorithm to be parallel friendly. From your description, your algorithm is probably not suitable, if each step, depends on the previous step result. https://softwareengineering.stackexchange.com/q/238729/161734
  20. Dalija Prasnikar

    VCL and VCL styles - bugs and future

    There are two separate things here. VCL and VCL Styles. You said that VCL is being abandoned by Embarcadero and that is simply not true as there is a huge difference between "not receiving too many features" and being abandoned. Also by "not receiving too many features" I definitely didn't want to say it barely received any. There were numerous features introduced in VCL since XE2, some were VCL only, some were both VCL and FMX. The part with bugs and IDE and "overnight fixing" is strictly related to VCL Styles. Only introducing styles to IDE exposed how buggy they really are and how much fixing they need. And that amount of fixes cannot be made overnight. VCL is mature framework. I never said that for VCL Styles. VCL Styles were never mature, they are just feature that was never properly finished in the first place. I hope this is more clear now.
  21. Dalija Prasnikar

    TTreeNode leak when VCL styles are active

    I opened new thread for more general discussion about VCL and VCL Styles
  22. Dalija Prasnikar

    Are you successful with form factors?

    You are describing bad web page (I know there are plenty of those in the wild). This is not how web pages should behave 🙂 Nor any other GUI... In general, most mobile designs have some kind of scrollable container as root and then you adapt your content to fit the screen width, and what does not fit, you wrap it around. Additionally, you can have some fixed top or bottom bar for navigation. Only the simplest screens with just few controls, can avoid scroll bar.
  23. Dalija Prasnikar

    Are you successful with form factors?

    I am afraid that your wishes are not aligned with reality. Unless you write your application for specific customer, targeting specific devices (screen sizes), your layouts will need to be dynamically adjustable. Like @Rollo62 said, this is mission impossible with zillion devices on the market. I think that using different form size layouts will only make things more complicated, than adjusting layout at runtime, even if you need to tweak it through code.
  24. Dalija Prasnikar

    Possible D10.4.2 issue..

    This sounds awfully familiar with this issue https://quality.embarcadero.com/browse/RSP-33140 But this issue shows when VCL Styles are used. Maybe something else got broken...
×