Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 03/29/24 in all areas

  1. Nice list, thanks 👍 You missed these few, probably: https://rosettacode.org/wiki/Parse_command-line_arguments#Delphi https://docwiki.embarcadero.com/Libraries/Alexandria/en/System.SysUtils.FindCmdLineSwitch https://github.com/exilon/QuickLib/blob/d085aa28e5fd65bae766446f5355ec4dc80fae9e/Quick.Commons.pas#L1292 https://wiert.me/2015/05/13/on-the-delphi-tcommandparser-class-for-parsing-command-lines-and-arguments-via-suggestions-for-how-to-define-command-line-parameters-stack-overflow/ https://github.com/jackdp/JPLib/blob/master/Base/JPL.CmdLineParser.pas https://github.com/tokibito/delphi-argparse
  2. This is a "classical" problem with Delphi, overloaded functions, and floating points values. IMHO using currency is an awful workaround here, and should not be kept in any serious codebase. It works "by chance". Another workaround, still using the Math unit, is to make the computation in two steps: function RoundExDouble(x: double): Double; begin x := x * 10; Result := Ceil(x) / 10; end; function RoundExInteger(x: double): Integer; begin x := x * 10; Result := Ceil(x); end; So the expected Ceil(double) overload is clearly picked up by the compiler. Or define our own unique Ceil() function, which does not depend on Math.pas and ensure we use the right value type: function ceil(x: double): integer; begin result := trunc(x) + ord(frac(x) > 0); end; This is this solution I used in my entry of the challenge: stay away from Math.pas. 😉
  3. var c : currency; begin c := Wert * 10; .... should make it calculating the same on all platforms, but I'm AFK at the moment.
  4. Remy Lebeau

    Bugs - where to write to fix it?

    In case anyone is not already aware of this https://quality.embarcadero.com is now in a permanent read-only mode. A new system is being implemented, but has not been opened to the public yet. So, if you do have a legit bug/feature to report, feel free to post it in a public forum, or write to Embarcadero directly, and someone who has internal access to the new system can open tickets for you until the new system is ready for public use.
  5. Remy Lebeau

    method for get file

    No. Using a share path only works on the local LAN network, and only if the file is exposed by the server to the LAN via a UNC share to begin with. If you want to copy a file over the Internet, you need to setup a suitable TCP server for that, such as an HTTP or FTP server.
  6. The event is signaled when TerminatedSet() is called. TerminatedSet() is called by the Terminated property setter. If the thread is still running when the TThread object is being destroyed, the inherited destructor will set the Terminated property and wait for the thread to finish running.
  7. That means you are creating the TTimer in the main thread to begin with, not in the background thread. That's exactly how TTimer already works. Its constructor creates a hidden window in the calling thread, which when activated will then receive timer messages from that same thread. So the thread that creates the TTimer must have a message loop to receive and dispatch those timer messages. So, you might think about moving the creation of the TTimer into the background thread's Execute() method, and that may work 99% of the time, but know that the creation of that hidden window is not done in a thread-safe manner, so you really should not be using TTimer in a background thread at all. If you really need a thread-based timer, you could just use the Win32 timeSetEvent() function, which is a multimedia timer that runs its callback in a background thread that the OS manages, If you really want to use a custom TThread class, then using TEvent is the simplest option that allows you to terminate the thread on demand, eg: uses ..., Classes, SyncObjs; type TTimerThread = class (TThread) private fEvent: TEvent; fInterval: LongWord; fOnElapsed: TNotifyEvent; protected procedure Execute; override; procedure TerminatedSet; override; public constructor Create(AInterval: LongWord; AOnElapsed: TNotifyEvent); reintroduce; destructor Destroy; end; constructor TTimerThread.Create(AInterval: LongWord; AOnTimer: TNotifyEvent); begin inherited Create(False); fInterval := AInterval; fOnElapsed := AOnElapsed; fEvent := TEvent.Create; end; destructor TTimerThread.Destroy; begin fEvent.Free; inherited Destroy; end; procedure TTimerThread.TerminatedSet; begin fEvent.SetEvent; end; procedure TTimerThread.Execute; begin while fEvent.WaitFor(fInterval) = wrTimeout do fOnElapsed(Self); end;
  8. I disagree. Sleep is only appropriate if the interval is very small and even then I wouldn't use it. The problem is thread termination; If you are using Sleep then the thread cannot be terminated while Sleep is executing. IMO the better solution, as have already been suggested, is to wait on an event with a timeout: If the event times out, do the task. If the event is signaled, terminate the thread. To terminate the thread, signal the event. While waiting on an event is much more complicated than just calling sleep, if one is to use threads one might as well learn how to do these things. Threads are difficult and pretending they aren't will just lead to lessons learned, the hard way, later on.
  9. You cannot terminate the thread while it's blocked by sleep. +1 for SimpleEvent and Waitfor.
  10. Dalija Prasnikar

    Help needed - ANR on Android app UI refresh

    RTTI had (and possibly still has) issues with thread safety when acquiring and releasing pool token. Unless you are using Windows application with dynamically loaded packages, the best option to avoid those issues is to call TRttiContext.KeepContext; in initialization section of some base unit and TRttiContext.DropContext; in finalization section. This will create pool token and keep it alive during lifetime of you application, avoiding thread safety issues, and it will also speed up RTTI operations.
×