-
Content Count
1111 -
Joined
-
Last visited
-
Days Won
96
Everything posted by Dalija Prasnikar
-
About Delphi 11.3 CE Platform Selection
Dalija Prasnikar replied to ChenShou's topic in Delphi IDE and APIs
Linux is only supported in Enterprise or higher SKU. Not even Professional SKU has Linux support. https://www.embarcadero.com/products/delphi/product-editions -
Why does a stack overflow cause a VCL application to terminate?
Dalija Prasnikar replied to Der schöne Günther's topic in RTL and Delphi Object Pascal
Now we are going into territory I don't know well. When guard pages are used, recovering from stack overflow exception requires some "manual" handling. While I don't know what Delphi actually does when it happens, it is fairly obvious that stack overflow exception corrupts memory as applications die almost immediately afterwards due to random AV exceptions or just get killed by the OS. -
What is the meaning of 2 In here
Dalija Prasnikar replied to stacker_liew's topic in RTL and Delphi Object Pascal
2 is Stride parameter. However, it does not actually do what people think it does. It divides work in chunks that will run on same task effectively limiting number of threads used for running parallel for loop at a time. Default value of stride is 1 which means that each pass will run independently of others. If the stride is 2, then Max number will be divided with 2 and there will be Max/2 number of chunks - tasks. If the Stride is same as Max then all passes will run inside single task. Someone writing this code though that stride defines index increments, but that is not so. Procedure will still run for each index from lower bound to upper bound regardless of stride value and calculation of prime numbers will be run for index 1, 2, 3,... -
Why does a stack overflow cause a VCL application to terminate?
Dalija Prasnikar replied to Der schöne Günther's topic in RTL and Delphi Object Pascal
As the name says, stack overflow overflows the memory buffer reserved for stack. In other words, it writes data in memory that does not belong to the particular stack buffer. This can corrupt parts of memory used for something else and this is also why stack overflow exception is not recoverable and can crash the application. -
Your thread class Execute method is basically empty. Is there any other code in there you didn't show? If not then that is the reason your code is running sequentially, as threads don't do anything. Also using lower priority for threads can make threads wait longer to get the CPU slice.
-
There are always other requirements besides speed. If the vendor requires support for many platforms then Electron is one of the available options that fits. Other requirements may be based on developers they have and their skillsets, as well as application features and target audience. For instance VSCode being written in Electron is foundation of their thriving plugin system not only because underlying technology is very suitable for that, but also because there is vast number of developers that can write those plugins.
-
Are you sure that poor speed is acceptable on desktop applications? What about applications that need to load complex forms where opening such form can take half a minute or more? Or when you need to create plenty of business objects, or when you need to do some textual processing. Good compiler means a lot in such cases. In last few Delphi releases @Stefan Glienke has continuously submitted hand crafted code to improve speed of some widely used RTL routines that have impact on overall performance. With better compiler that would not be necessary. Not only that, but with better compiler all other code we write would be faster and when speed matters we wouldn't have to bend over backwards, writing horribly unreadable code just to get the speed we need. We could just write the clean and readable and maintainable code and leave the dirty work to the compiler. Speed always matters. Now, Delphi still might be fast enough for many purposes, but for many that is simply not enough. Once it was state of the art compiler, now it is seriously falling behind.
-
I am sorry, but snippets of code where it is not clear what happens at which point and how everything is created and called are also not enough to figure out what exactly is wrong with your code. One of the things does sound suspicious: you say the thread is stuck in the limbo when timeout occurs and you have Sleep call which will cause thread to sleep if it is not terminated, Maybe there is a problem?
-
It is impossible to say what is going on without seeing your code.
-
Your code logic sounds backward. You should run code in FormCreate inside the calling form and then depending on the result create TChangesLogForm or not. Or if the code really belongs to TChangesLogForm, you should not run that code within FormCreate, but after the form is shown (along with some indication that there is a work in progress) and then if there is an error retrieving the data, you can show error message and close the form in that moment.
-
Httpclient asynchronous callback and Httpclient.endAsyncHttp
Dalija Prasnikar replied to pavlos's topic in Network, Cloud and Web
Following code would do the job procedure TUExtractForm.LoadURLAsyncPOST(const AURL, AText: string); const CONST_TIMEOUT = 1000; begin TTask.Run( procedure var HttpClient: TNetHTTPClient; HTTPRequest: TNetHTTPRequest; ParamsStream: TBytesStream; begin ParamsStream := nil; try HttpClient := TNetHTTPClient.Create(nil); try HttpClient.ConnectionTimeout := CONST_TIMEOUT; // Timeout HttpClient.ResponseTimeout := CONST_TIMEOUT; // Timeout HTTPRequest := TNetHTTPRequest.Create(HttpClient); HTTPRequest.Client := HttpClient; HTTPRequest.OnRequestCompleted := HTTPRequestCompleted; HTTPRequest.OnRequestError := HTTPRequestError; HTTPRequest.CustomHeaders['Content-Type'] := 'application/x-www-form-urlencoded'; ParamsStream := TBytesStream.Create(TEncoding.UTF8.GetBytes('input=' + TNetEncoding.URL.Encode(AText))); HTTPRequest.Post(AURL, ParamsStream); finally HttpClient.Free; ParamsStream.Free; end; except on E: Exception do begin TThread.Queue(nil, procedure begin ShowMessageFmt('Error: %s', [E.Message]); end); end; end; end); end; procedure TUExtractForm.HTTPRequestCompleted(const Sender: TObject; const AResponse: IHTTPResponse); var Content: string; begin if AResponse.StatusCode = 200 then begin Content := AResponse.ContentAsString; // replace #$A with new line Content := StringReplace(Content, #$A, sLineBreak, [rfReplaceAll]); URLMemo.Text := Content; end; end; procedure TUExtractForm.HTTPRequestError(const Sender: TObject; const AError: string); begin ShowMessageFmt('Error: %s', [AError]); end; However, your timeout setting is very low - one second, and this can cause issues if the server does not respond timely. I would just use default settings.- 9 replies
-
- networking
- httpclient
-
(and 1 more)
Tagged with:
-
Httpclient asynchronous callback and Httpclient.endAsyncHttp
Dalija Prasnikar replied to pavlos's topic in Network, Cloud and Web
TTask.Run already runs in background thread and that thread will not finish before HTTP client completes its work or times out. You don't need to run another thread inside task and you don't need to run a loop simulating timeout.- 9 replies
-
- networking
- httpclient
-
(and 1 more)
Tagged with:
-
Httpclient asynchronous callback and Httpclient.endAsyncHttp
Dalija Prasnikar replied to pavlos's topic in Network, Cloud and Web
I am not sure about that. THTTPClient has built in support for timeout. What are you trying to accomplish with your timeout implementation? Your code is needlessly complicated.- 9 replies
-
- networking
- httpclient
-
(and 1 more)
Tagged with:
-
Httpclient asynchronous callback and Httpclient.endAsyncHttp
Dalija Prasnikar replied to pavlos's topic in Network, Cloud and Web
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);- 9 replies
-
- networking
- httpclient
-
(and 1 more)
Tagged with:
-
How to fix W1055 Published Caused RTTI ($M+) Warning
Dalija Prasnikar replied to egnew's topic in RTL and Delphi Object Pascal
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; -
How to fix W1055 Published Caused RTTI ($M+) Warning
Dalija Prasnikar replied to egnew's topic in RTL and Delphi Object Pascal
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. -
Access Violation when Enabling TTimer in TComponent
Dalija Prasnikar replied to egnew's topic in RTL and Delphi Object Pascal
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) -
Delphi 11 DelphiLSP "A valid license was not found. Please contact Embarcadero Support"
Dalija Prasnikar replied to Al T's topic in Delphi IDE and APIs
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 -
E2137 Method not used in base class
Dalija Prasnikar replied to Willicious's topic in Delphi IDE and APIs
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 -
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.
-
Yes, it is a good idea to show user the reason why form cannot be closed.
-
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.
-
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.
-
Are TCompressionStream and TDecompressionStream thread safe?
Dalija Prasnikar replied to c0d3r's topic in Algorithms, Data Structures and Class Design
Yes, those two stream classes can be safely used in background threads if they are not shared. -
E2137 Method not used in base class
Dalija Prasnikar replied to Willicious's topic in Delphi IDE and APIs
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.