Jump to content

Dalija Prasnikar

Members
  • Content Count

    1148
  • Joined

  • Last visited

  • Days Won

    106

Everything posted by Dalija Prasnikar

  1. If you want to use asynchronous mode for HTTP requests you should use TNetHTTPClient instead of THTTPClient. TNetHTTPClient is a wrapper that implements all the gory details in the background and leaves easy to use API for the developer. https://docwiki.embarcadero.com/Libraries/Sydney/en/System.Net.HttpClientComponent.TNetHTTPClient As far as synchronizing events is concerned, in THTTPClient they will run in the context of the background thread, so you need to synchronize them with main thread if you need to access the UI. TNetHTTPClient has property SynchronizeEvents and depending on its value events will run synchronized with the main thread or not. Default value is True, so events will run in the context of the main thread. If you drop TNetHTTPclient on the form you can use it in asynchronous mode with just few lines: Client.Asynchronous := True; Client.OnRequestCompleted := HTTPRequestRequestCompleted; Client.Get(’http://....’); However, asynchronous mode is hard to debug and control, and I would suggest using simpler approach using background threads or tasks. TTask.Run( procedure var Client: THTTPClient; Response: IHTTPResponse; begin Client := THTTPClient.Create; try Response := Client.Get('...'); finally Client.Free; end; // process response in background thread ... // or pass it to the main thread TThread.Queue(nil, procedure begin Memo.Lines.Add(Response.ContentAsString); end); end);
  2. Well in that case you should do what the warning suggests. Add {M+} compiler directive before the class declaration or you can inherit from TPersistent which has RTTI generation turned on. type {$M+} TisEventHandler = class published procedure isPrintScreenClick(Sender: TObject); end;
  3. Usually published directive is used in Delphi component streaming system for properties in components that will be set in design time and saved as part of form, frame or data module. You have used it for declaring a method and this is not a common use case (unless you want to find and invoke the method by using its name through RTTI). You probably wanted to use public directive instead of published in your code. This will remove the warning.
  4. To tell what is wrong, we need to see your class declaration and implementation - in this case most likely constructor is what matters. Showing TTimer code is not very helpful. So when you ask for help, you should post your code first. However, knowing that your code works when you construct component directly and it does not when you drop it on a form, narrows down potential cause and most likely culprit is that you didn't add override directive to your component constructor. When you call constructor directly specifying its class then your constructor will run and create timer component, but when you drop it on a form original virtual constructor chain from TComponent will run, but it will skip calling your constructor because it is not marked as part of the chain (missing override directive). type TMyComponent = class(... ... public constructor Create(AOwner: TComponent); override; ens; If that is the case, you would also see warning W1010 Method 'Create' hides virtual method of base type... This warning tells you that something is wrong with your declaration and that you most likely forgot to add override directive (there are other scenarios besides this one, but in your case this is the one that matters)
  5. Maybe someone here had similar issue, but the fastest way to get help would be to contact support like the message says. You can do that through web. Make sure you choose Registration & Instalaltion https://www.embarcadero.com/support
  6. Dalija Prasnikar

    E2137 Method not used in base class

    Override is used when you want to override virtual or dynamic method from the base class and change its behavior https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Methods_(Delphi)#Virtual_and_Dynamic_Methods
  7. Dalija Prasnikar

    Not Threadsafe??

    Like @Remy Lebeau already said, both his and mine solution will do that. Your UI will be responsive as VCL main message pump will keep running while your thread is doing work in the background. If you are confused by DisableUI/EnableUI method names, code in those methods will not block that message pump either unless you put some infinite loop there on purpose. Both can be completely empty. You should put there code that will show/hide progress spinner or you can disable/enable some buttons so that user cannot start some other operation while backup is running.
  8. Dalija Prasnikar

    Not Threadsafe??

    Yes, it is a good idea to show user the reason why form cannot be closed.
  9. Dalija Prasnikar

    Not Threadsafe??

    While more complicated scenario with multiple threads could require more sophisticated code, this approach would work without issues even if there are multiple tasks that require running in background thread. There would be no chaos because only single thread can run at the time. This is what "if Processing then Exit" is here for. User will not be able to start another thread as long as some thread is already running. Only when thread finishes, new thread can be started.
  10. Dalija Prasnikar

    Not Threadsafe??

    Application.ProcessMessages in not thread-safe means you cannot call it from the background thread. Since you are calling it from main thread that alone is not a problem in your code. However, one of the points of using threads is to keep application responsive to messages so you don't have to use Application.ProcessMessages which is not the best practice for many reasons. There are many ways for handling threads, and which one you choose depends on what particular thread does and the application logic. Since your code actually waits until the operation completes, then the simplest code that would achieve what you want with threads would be something like this: TMainForm = class(TForm) private Processing: Boolean; procedure EnableUI; procedure DisableUI; ... end; procedure TMainForm.BtnClick(Sender: TObject); begin if Processing then Exit; Processing := True; try DisableUI; TThread.CreateAnonymousThread( procedure begin try // do work here finally TThread.Queue(nil, procedure begin EnableUI; Processing := False; end); end; end).Start; except EnableUI; Processing := False; end; end; procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin CanClose := not Processing; end; In EnableUI and DisableUI methods you can put whatever code you need to show the user that you are doing some work or disable/enable some actions. The rest is pretty simple - if user tries to start processing again, code will not let it do that (that is something you should have even when you use Application.ProcessMessages as it allows reentrancy and user could start same operation while previous one is not finished). When thread is done (regardless of whether it completes successfully or not), it will enable UI (this needs to be called from the main thread and this is why there is TThread.Queue (or you can use TThread.Synchronize here - the main difference is that Queue is non blocking call and Synchronize is blocking). You can also catch exceptions and show message to user in similar manner. Thread will self-destruct after it is finished so you don't have to worry about its memory management. To avoid complicated cleanup and potentially breaking unfinished work thread is doing, the simplest way is to prevent user from closing form while thread is working in FormCloseQuery event. Note: Running DBSBackup.Execute opens the question about thread-safety of that code - in other words whether main thread can use DBSBackup instance and anything directly related while thread is running - which would not be thread-safe to do. But that part is another story.
  11. Yes, those two stream classes can be safely used in background threads if they are not shared.
  12. Dalija Prasnikar

    E2137 Method not used in base class

    This error happens when you add override directive to the method and method with same name does not exist in the class hierarchy from which you are inheriting. If you just wanted to add new method which does not exists, then remove override. The "check spelling" suggestion comes from the most common mistake when overriding existing method is that you mistype the name, so the name does not match to the name of existing method in base class which you want to override.
  13. Generally any kind of stream should be suitable for using in background threads, but also they cannot be simultaneously accessed and shared between threads. Just look at it logically - how can you use stream that holds a state (if nothing else than current position that changes as you read and write) be thread-safe? While you could in theory protect simultaneous access with locks and share stream across threads, you wouldn't gain much from that as stream would have to be locked and accessible to one thread at the time. If you think you could speed some operation by sharing stream and using is in parallel, you will only slow the whole process down, not speed it up. When using TCompressionStream and TDecompressionStream in background thread, OpProgress event handler will run in the context of background thread and you need to take that into account if you want to show progress in the UI and synchronize code.
  14. Why? iOS users know how to move application to the background using Home button. Such functionality does not belong in the iOS application. Just remove the Exit button or hide it on the iOS and avoid calling problematic code on iOS with compiler directives.
  15. iOS does not support terminating application, so Delphi does not have that support either. If Delphi previously implemented Terminate on iOS it was most likely removed as such functionality would cause rejection on the AppStore. See https://stackoverflow.com/questions/355168/proper-way-to-exit-iphone-application
  16. @PaulM117 like Lars suggested, if you can create test case, please submit a bug to Quality Portal. However, even if you cannot create reproducible test case, submitting a bug report (with as much information as you can provide) might still be a good choice as at least it gives some feedback to Embarcadero that there is something seriously broken in the area.
  17. I have noticed that switching between platforms often chokes if you just compile or do syntax check. Full build works. It seems like some internal compiler status or cache is not properly cleaned during platform switching. However, I haven't been able to create small reproducible test project to report the issue and I don't switch platforms that often so I never tried to investigate deeper. The issue sounds like it is cache related, so I would say that enabling cache option might be counter productive. Try disabling the cache and see how it goes.
  18. Dalija Prasnikar

    VCL and VCL styles - bugs and future

    Implemented what? If you mean full thread-safe UI, then no. For one thing Windows API has thread-affinity, meaning that you cannot create windows in one thread and use it in other. There is currently another thread that talks about FMX and VCL thread safety as well as Windows API thread safety and what can and cannot be done any why.
  19. Dalija Prasnikar

    Creating FMX controls in a background thread

    You can do that, but you can only use non-blocking communication. This means SendMessage is out of the question as it can deadlock. This means that your hierarchy of controls must be specifically handled to allow such usage. Which means using Windows API directly for creating such controls. Any steps into using VCL or FMX to do that are recipe for disaster. Yes, I know that people are doing all kinds of things and that it "works" but they are just being lucky. I am not going to say, yes you can do that when you are out of options, because then people stop and don't look for other options. Another problem is recognizing all thread-safety issues as UI is complex and interactions are also complicated and it is very easy to miss problematic scenarios. Again, they are just being lucky. We need better controls and libraries that can perform heavy tasks outside UI controls and main thread.
  20. Dalija Prasnikar

    Creating FMX controls in a background thread

    No you are not calling a task as in something that will create and run on different thread, you are merely calling a piece of code (function) that will run in the context of your thread. There is no separate OS API thread. your application runs in one OS thread. IN terms of OS application is a process. When you run application you are starting a process that will create and run in new thread. but if your application does not explicitly create another thread everything will just run in that one thread, even when you call Windows API.
  21. Dalija Prasnikar

    Creating FMX controls in a background thread

    The thread from which you call Windows API. When you call API like CreateWindow or you create object in Delphi there are no other threads involved. (Unless specific API or object is specifically meant to handle thread functionality or is part of some asynchronous API)
  22. Dalija Prasnikar

    Creating FMX controls in a background thread

    Yes, you can have control that completely runs in the different thread that runs its own message loop. That is different scenario from the one I said - constructing the controls in background thread and then using them in main thread. Using (inside main thread) and merely communicating (sending messages are different things. There are boundaries between controls that belong to different threads. In other words there are different levels of thread-safety. Since Windows API has thread affinity, it is not fully thread-safe. In practical terms having such application means that you need to deal with more complexities in places where you otherwise wouldn't, Using UI in same thread means you can use SendMessage to perform operations quickly because in the context of same thread SendMessage will avoid the message queue and will simply run the windows proc. However, when you SendMessage to window that belongs to different thread, SendMessage will go through message queue. But, SendMessage is blocking call and in complex to-way communication between two threads with SendMessage you can easily cause deadlock. OK, solution to that is that you don't use SendMessage, but only non blocking communication, which is slower. and that would probably work if you handle all those windows manually directly through Windows API and you exactly know to which thread they belong to. Assing any abstraction layer on top your be a nightmare (this is where we start stepping into Delphi RTL and visual frameworks). Again, thread affinity is what makes it thread-unsafe. Now, you may have different viewpoint on what thread-safe is in this context, but not being completely thread-unsafe is still far from being completely thread-safe. Some additional reading: https://devblogs.microsoft.com/oldnewthing/20051010-09/?p=33843 https://devblogs.microsoft.com/oldnewthing/20051011-10/?p=33823 https://devblogs.microsoft.com/oldnewthing/20051012-00/?p=33803 https://devblogs.microsoft.com/oldnewthing/20051013-11/?p=33783
  23. Dalija Prasnikar

    Creating FMX controls in a background thread

    There is way more in UI thread safety than thread safe communication between controls. In Windows API windows can communicate across thread-boundaries, but each window still belongs and is bound to a thread where it is created and that thread's message queue. This basically prevents you to create window control in one thread (background) and use it in another (main).
  24. It is fine if you find ChatGPT useful for something. But just because it is useful to you, does not mean it is useful to others.
  25. Dalija Prasnikar

    Alexandria 11.3 and Android 13 (part 2)

    This version number is not SDK version it is tools version. SDK version for supporting Android API levels is set in SDK panel in Options dialog under "SDK API level location". You can find which SDK platforms you have installed in SDK\platforms folder. Fro API 33 there should be android-33 folder inside. Also Java interfaces don't change with each API version and they are pretty stable, so they don't need to be constantly updated. Occasionally, when new API has some additional features or some interfaces are changed Delphi Java interfaces will be changed accordingly. When Embarcadero says they support some API level, that means they actually do support that API level.
×