Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 09/14/23 in all areas

  1. Remy Lebeau

    ProcessMessages doesn't seem to update controls

    BCB6 predates Visual Styles and VCL Styles and basically most modern UI practices. For example, when UI changes are animated by the OS or Styles, it would thus take multiple paint cycles to fully animate the complete state change, and ProcessMessages() or Update() may not (likely will not) catch all of the paint cycles in a single call. You can mitigate that somewhat by using thread pools, for instance. There is nothing in UI programming that says like "state change is finished and the UI for it is fully drawn". Not even back in BCB6's day. Although back then, drawing was much simpler, and usually completed in 1 paint cycle. That may not be the case anymore in modern UIs. That is not really a factor of the property itself, but in the UI rendering behind the scenes, so more oriented to differ between OS versions rather than compiler/VCL versions. Update() only processes paint messages that are already pending in the message queue. But you also need Invaliidate() to generate those messages in the first place, if they are not already generated for you. So that is where Repaint() comes into play, to signal that a new paint cycle is needed if it hasn't already been signaled.
  2. Remy Lebeau

    ProcessMessages doesn't seem to update controls

    Yes, it does. But it can only handle messages that are already in the message queue (or synthetically generated by the queue) at the moment it is called. It does not process future messages. And the behavior you describe sounds like the actions are being delayed such that ProcessMessages() doesn't see all of them right away, which is why calling ProcessMessages() multiple times produces better results. You really should not be using ProcessMessages() in this manner in the first place. Break up your code logic using TThread::ForceQueue() or a TTimer or equivalent to allow control to flow back into the main message loop so it can continue to process new messages while your desired time interval is waiting to elapse. For example, using TThread::ForceQueue(): void __fastcall TForm1::Button1Click(TObject *Sender) { Button1->Enabled = false; Button2->Enabled = false; Button3->Enabled = false; TThread::ForceQueue(nullptr, &Step2, 3000); } void __fastcall TForm1::Step2() { Button1->Enabled = true; Button2->Enabled = true; Button3->Enabled = true; TThread::ForceQueue(&Step3, 3000); } void __fastcall TForm1::Step3() { //... } // alternatively void __fastcall TForm1::Button1Click(TObject *Sender) { Button1->Enabled = false; Button2->Enabled = false; Button3->Enabled = false; TThread::ForceQueue(nullptr, [this](){ Button1->Enabled = true; Button2->Enabled = true; Button3->Enabled = true; TThread::ForceQueue(nullpr, [](){ //... }, 3000); }, 3000); } Or, using TTimer: void __fastcall TForm1::Button1Click(TObject *Sender) { Button1->Enabled = false; Button2->Enabled = false; Button3->Enabled = false; //Timer1->Interval = 3000; Timer1->Tag = 1; Timer1->Enabled = true; } void __fastcall TForm1::Timer1Timer(TObject *Sender) { if (Timer1->Tag == 1) { Button1->Enabled = true; Button2->Enabled = true; Button3->Enabled = true; //Timer1->Interval = 3000; Timer1->Tag = 2; } else { //... Timer1->Enabled = false; Timer1->Tag = 0; } } // alternatively... void __fastcall TForm1::Button1Click(TObject *Sender) { Button1->Enabled = false; Button2->Enabled = false; Button3->Enabled = false; //Timer1->Interval = 3000; Timer1->OnTimer = Step2; Timer1->Enabled = true; } void __fastcall TForm1::Step2(TObject *Sender) { Button1->Enabled = true; Button2->Enabled = true; Button3->Enabled = true; //Timer1->Interval = 3000; Timer1->OnTimer = Step3; } void __fastcall TForm1::Step3(TObject *Sender) { //... Timer1->Enabled = false; Timer1->OnTimer = nullptr; }
  3. Hi I created a ticket a while back on Quality Portal for some missing Windows SDK functions for Fibers. I created a small test project to illustrate them working in https://github.com/sempare/sempare-delphi-fiber-generator. For those that don't know, fibers essentially are light weight threads, where context switching between fibers is managed by the developer and not by the OS, as is done with threads. It can be complex to get your head around them if you are not familiar with them. For a more detailed discussion, here is a nice article: https://nullprogram.com/blog/2019/03/28/ and https://learn.microsoft.com/en-us/windows/win32/procthread/fibers. I think the reason they were omitted in the Delphi Windows unit is because the tool that did the main conversion of the Windows SDK functions was working with normal C functions, where the missing functions I've included were defined as C macros. From a Delphi perspective, GetFiberData annd GetCurrentFiber are available in the unit https://github.com/sempare/sempare-delphi-fiber-generator/blob/develop/src/Sempare.Win32.Fiber.pas for win32 and win64. In the project, the unit https://github.com/sempare/sempare-delphi-fiber-generator/blob/develop/src/Sempare.FiberGenerator.pas contains a TGenerator<T> which switches between the procedure producing values and the main method that is consuming them. Here is an example of it in use with a fibonacci generator. So what is going on here.... A producer is a procedure that must call Yield(value). So we know that with Fibonacci, f(0) =1, f(1) =1, f(n) = f(n-1) + f(n-2). Rather than having a recursive routine, the producer method simply Yields the values appropriately. Yes, it looks like the method will never stop. That doesn't matter. Once the method has a value to yield, the context is switched back to the main bit of code that is requesting the value ... that where we have: As mentioned, this is just a simple demo of using fibers. Another project I had that has a bit more complex utilisation of fibers was for async IO on sockets - the principle was to make async calls with call back functions appear synchronous, which is what most people are more comfortable with. Even though most people will never need to use the fiber methods directly as I illustrated above with the TGenerator example, it is quite a powerful tool in the toolbelt.
  4. Vincent Parrett

    Playing with Windows Fibers by emulating Python Generators

    I came across this interesting comparison yesterday between Goroutines and C# async/await (part of a group of articles comparing the languages). https://alexyakunin.medium.com/go-vs-c-part-1-goroutines-vs-async-await-ac909c651c11 Well worth a read. TLDR - Goroutines are faster, easier to use than async await (async everywhere is a pain), stack sizes matter and Go runs out of memory long before C# - in the benchmarks at least.
  5. DelphiUdIT

    ProcessMessages doesn't seem to update controls

    As documentation says: So, is better to use directly Update for each control after every "enabled = false". I tried and for me is working, but I really don't know if it's OK in all situation (i.e. under heavy load).
  6. DelphiUdIT

    ProcessMessages doesn't seem to update controls

    I don't use c++ to build interfaces, only for device interfacing. I normally use Delphi instead, but the principle is the same: when you use any property of a component (but also functions, procedures, methods, etc ...) especially graphical components, i.e. which is executed "behind" the property it can be synchronous or asynchronous. So you cannot in any way expect that your action will have an immediate response, especially with graphics. Normally the graphics have a lower priority level (let's call it that) than the standard code and it is still unlikely that the graphics will be able to follow the code in real time (and it doesn't even make sense normally). To clarify the situation better, I present the use of the "SendMessage" and the "PostMessage". Both perform the same function, i.e. send messages to the queue.... but while SendMessage "makes sure" that the message is deposited and returns to the caller only after the message has been deposited in the queue (synchronous operation with your code), PostMessage instead sends it to the queue and returns immediately, without making sure that it is actually in the queue (the message will arrive in the queue asynchronously with respect to your code). With SendMessage at the next line of your code it is certain that the message is present in the queue, with PostMessage it is not certain (and no time prediction can be made) that the message is present at the queue of the next line of your code.
  7. aehimself

    ProcessMessages doesn't seem to update controls

    I am using Delphi exclusively but I suppose it'll be similar in CB too. Forget about ProcessMessages. If you really need, you can call Button1.Repaint for example. This will skip the message queue and simply "force" the control to refresh it's appearance.
  8. This project deserves some attention (greenlets-coroutines, generators, channels and more). It is based on fibers.
  9. sjordi

    Android Create SQLLite Database at Runtime.

    Do you have permissions to write the DB? Did you try to write a test file like "test.txt"? If it doesn't work, you don't have write permissions. Otherwise please provide the error message (if any) you get when creating the DB
  10. Fibers under the magnifying glass Gor Nishanov (gorn@microsoft.com) - author? of c++ coroutines (Advocating coroutines over fibers.) Abstract "Fibers (sometimes called stackful coroutines or user mode cooperatively scheduled threads) and stackless coroutines (compiler synthesized state machines) represent two distinct programming facilities with vast performance and functionality differences. This paper highlights efficiency, scalability and usability problems of fibers and reaches the conclusion that they are not an appropriate solution for writing scalable concurrent software." https://open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1364r0.pdf
  11. Angus Robertson

    How to validate the public key

    This fix is now in SVN and the overnight zip, property X509PubKeyTB in TX509Base will get the certificate public in DER binary format as TBytes, from where it may be converted to hex or base64, and used for Raw Public Key certificate validation. At least assuming the raw key distributed is the DER format. It seems comparing a SHA256 digest is common, rather than a long string. Angus
  12. It worked just fine. Thank you very much!
  13. I do find the mixed response in this thread really interesting. When I raised the RSP, Brian Long, an long time Delphi guy, asked if I had tested the routines and I said I'd provide an example test project. Most missed the intent to facilitate completeness as I did not labour that point too much. I thought providing the missing routines and tests is something that could be useful to to anyone else that was curious/explorers/prototypers, etc. I agree, 99.9% of coders will never need to go near this stuff. Open question - should there be a blanket ban on experiments or using stuff that nobody else does because it is deemed obsolete (g*d, how many times have I heard that about Delphi/Pascal). Just putting it out there....
  14. Stefan Glienke

    Playing with Windows Fibers by emulating Python Generators

    https://bitbucket.org/sglienke/spring4d/branch/feature/coroutines - the reasons it never made it into the main branch are what has been mentioned before and the fact that on POSIX I emulate them using a thread and an event (which is deadly slow) - still until anyone convinces me otherwise (by showing some actual working code!) this is the closest we get to some conveniently usable coroutines in Delphi.
  15. David Heffernan

    Playing with Windows Fibers by emulating Python Generators

    I thought they'd been removed because they weren't useful. They were added for SQL server and in the end it turned out they weren't useful for that application.
  16. There are plenty of C macros that are translated into Delphi's Window SDK units. More likely, they were not translated simply because fibers are just not used by most developers, not even Microsoft: Fibers aren’t useful for much any more; there’s just one corner of it that remains useful for a reason unrelated to fibers
  17. Remy Lebeau

    Indy & OpenSSL 1.1.1 & TLS 1.3

    Status hasn't changed since the last time you asked. The new support code for OpenSSL 1.1.x and TLS 1.3 is still in Pull Request #299 on GitHub awaiting review and merge into the main codebase. AFAIK, it works in general, but I offer no guarantees about it yet as there are some open issues with it, cross platform support hasn't been tested, etc. It is not dead. I still work on it pretty frequently, but I'm pretty much the only developer working on it (aside from the occasional contribution from users or Embarcadero), and I just don't have the kind of free time that I used to have. But I do what I can with the time I can spare for it. Plus, it doesn't help that I don't have a working IDE installed anymore. Many years ago (I just checked my blog, and wow, I didn't realize just how many years have past now!), a series of multiple back-to-back system crashes took out my entire development environment - all of my VMs, NAS backups, laptop, everything gone. To this day, I still haven't recovered any of my old files yet. In the case of Indy specifically, fortunately the main code was stored online, so I can continue to checkin updates/fixes as needed, but I lost a lot of internal dev code I was working on at the time. As for the IDE itself, I just haven't committed time to reinstall it yet. I don't use RAD Studio in my day job anymore. Not to mention I haven't been very happy with all the problems I see people report in various online forums about the past handful of releases, so I've been hesitant to reinstall a new IDE for awhile. But, last year I did finally buy a new laptop for future dev work, and plan on installing RAD Studio onto it (eventually). I know, it sounds like I'm just making excuses. Maybe I am. I need to pick up the slack ...
×