Jump to content

Der schöne Günther

Members
  • Content Count

    658
  • Joined

  • Last visited

  • Days Won

    12

Everything posted by Der schöne Günther

  1. Der schöne Günther

    Is it possible to know when a TObject is instanciated/freed?

    Maybe this could be related? http://blog.marcocantu.com/blog/2017-june-delphi-packages-creators-update.html
  2. Der schöne Günther

    RadStudio Roadmap 2019

    What's so interesting about that? I still don't get quite behind that language server thing. I see that they will be able to delegate things like Code Completion and Error Insight to some external process in the background. Is that also going to work the other way round? Will tools like VS Code be able to access Delphi's debugger? I am already looking forward to 10.4 because of High DPI. Maybe I will once again be able to use Delphi at home, not just at work.
  3. Consider the following: uses System.Threading; procedure TForm1.Button1Click(Sender: TObject); var task: ITask; begin task := TTask.Run( procedure() begin raise EProgrammerNotFound.Create('test'); end ); try task.Wait(); // << raises EAggregateException except ShowMessage('ex'); end; task.Wait(); // no exception. returns true // task.Status is now TTaskStatus.Exception end; I find this irritating. Why does waiting for a task raise an exception one time, but not the other? Apart from the fact that the Embarcadero documentation on ITask.Wait(..) does not even mention an exception should be expected, I guess they (once again) modelled it after .NET's Task.Wait(..) method which clearly states an exception is to be expected if the task was cancelled or failed with an exception. Some fine gentleman even reported this to Embarcadero almost five years back: https://quality.embarcadero.com/browse/RSP-9548 But two years later, it was closed as "Works as expected". I still don't understand. Can someone elaborate? I believe the implementation is wrong.
  4. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    Thank you for taking the time to explain. It sounds like a good point, although a bit artificial 😉 And I have trouble achieving just that. Even with something like procedure TForm1.Button1Click(Sender: TObject); var task: ITask; e: Exception; begin event := TSimpleEvent.Create(); task := TTask.Run( procedure() begin raise EProgrammerNotFound.Create(EmptyStr); end ); try try task.Wait(); finally task := nil; end; except e := Exception( AcquireExceptionObject() ); end; end; The task still lives. Maybe because the default thread pool still has a reference to it.
  5. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    Thank you for replying. If that can happen, then yes, then that won't work. But right now, I have no idea how that could happen, to be honest. In order to catch the exception, I have to call .Wait() on the task - Meaning I have to have a reference to it. Meaning the task cannot be freed yet. What am I missing?
  6. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    And because of that, it's even more important the exceptions do not get lost and you get a reliable and reproducible behaviour. 😎 As so often, it seems to be modelled after .NET. And what .NET does (raise the exception(s) every time you wait for the task) is perfectly achievable with Delphi. I just don't understand why they took this weird approach.
  7. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    There is no need to change anything about raising exceptions or lifetime management of exceptions. It's just that an EAggregateException always owns the exception it refers to. I believe that should be optional. Raise the exception normally, or acquire ownership and free it later - It doesn't matter. As long as the task owns its exceptions, not the EAggregateException. You can do with the AggregateExcption whatever you like. It's not the same, but TThread is similar. It has a FatalException property you can query for the exception that happened in the thread. The exception is owned by the thread. It is there for as long as the thread object is alive. With the way tasks are implemented, the first one to call .Wait() on a task gets the exceptions - After that, they're gone. It makes no sense.
  8. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    But "the exception" is an artificially generated EAggregateException that references exceptions that are already stored. The "true" exceptions have never been raised directly. There would be nothing wrong with raising an EAggregateException that does not own the exceptions it referred and instead the task can free those exceptions when it is destroyed. Which is what was suggested in https://quality.embarcadero.com/browse/RSP-9548. Wouldn't that solve all those problems?
  9. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    Does that mean 10.3 raises an exception for both times? Because I accidentally typed it would raise an EOperationCancelled. It does, in fact, properly raise an EAggregateException. But just for the first time.
  10. Consider the following: I have a method that raises an EAggregateException that only contains one inner exception In my try block, I would like to extract the one inner exception and raise this instead. procedure raiseAggregate(); var innerExceptions: TArray<Exception>; aggregateException: EAggregateException; begin innerExceptions := [EProgrammerNotFound.Create('hello')]; aggregateException := EAggregateException.Create(innerExceptions); raise aggregateException; end; procedure TForm1.Button1Click(Sender: TObject); begin try raiseAggregate(); except on e: EAggregateException do begin if (e.Count = 1) then raise e.InnerExceptions[0] // <<< that would be too easy else raise e; end else raise; end; end; How do I do this? I cannot simply use raise e.InnerExceptions[0] because e gets destroyed at the end of the try..except block. This is a problem because e owns its inner exceptions. When e gets destroyed, I have basically raised a destroyed exception. In case you're not familiar with the System.Threading.EAggregateException, you check the .NET documentation. Embarcadero documentation does not exist.
  11. Der schöne Günther

    Is it possible to raise an aggregated exception?

    So far, the only solution I have come up with is ripping out the wanted exception with a class helper 🤷‍♂️ and then raise this exception instead. function EAggregateExceptionHelper.Extract(const index: NativeInt): Exception; var newArray: TArray<Exception>; arrayIndex: NativeInt; begin newArray := []; Result := nil; with self do begin for arrayIndex := Low(FInnerExceptions) to High(FInnerExceptions) do if(arrayIndex = index) then Result := FInnerExceptions[arrayIndex] else newArray := newArray + [FInnerExceptions[arrayIndex]]; FInnerExceptions := newArray; end; end;
  12. Der schöne Günther

    Git UI tools

    I don't use Visual Studio for Git, but Visual Studio Code with GitLens. And, from time to time, the Windows explorer integration from TortoiseGit. As far as I recall, Visual Studio didn't even have support for Git stashes until VS 2019.
  13. Der schöne Günther

    Forked VSCode for Delphi

    There's not just VSC. Have a look at this: I honestly couldn't care less about the form designer. As horrible as it actually is, it's probably just too much work to completely rewrite it for another environment. Proper debugging capabilities are way more important.
  14. Der schöne Günther

    Touchscreen signature

    Are you sure it's a capacitive touch screen or something more sophisticated that works with a "proper" pressure-sensitive pen? There are quite a lot of W10 devices that have an additional digitizer for pen input.
  15. Der schöne Günther

    Decorating read-only controls

    Interesting read: https://ux.stackexchange.com/q/84715
  16. Der schöne Günther

    Trouble with (very) simple XML-parsing

    Doesn't getElementsByTagName(..) only list direct descendants? You will either have to search recursively, or use something like an XPath expression to get all the nodes you are interested in.
  17. Der schöne Günther

    ANN: Find leaks in Delphi and C++ with Deleaker

    That looks very exciting, but I do find the prices a bit steep 😶 Does one license work with both RAD Studio and Visual Studio integration? For VS, does it find leaks for C++/CLI Mixed mode applications?
  18. Der schöne Günther

    SDTimes Industry Watch: The developer transformation

    In case anyone wonders, here is the original "study": https://stripe.com/files/reports/the-developer-coefficient.pdf Sure, this PowerPoint has nice colours and everything, but I really don't know what to make of things like (emphasis by me)
  19. Der schöne Günther

    Solution(s) for coder with quite poor eyesight

    I depend on contact lenses. When I don't have them in (at home), I can barely see anything. But then, I can just crank Windows DPI up to 200% and everything is fine on my 27" screen (2560x1440). Normally, I have 125% DPI on that screen. I am, however, not using Delphi at home anymore as it is extremely blurry on 125% DPI. All my other code editors don't have this problem and can instantly switch to higher/lower DPIs with no issues. At 200% DPI, the Delphi IDE should probably look fine, I never tried. What operating systems are you using? Quite some things have improved in the last versions...
  20. Der schöne Günther

    We use DUnitX and it discovers all our silly mistakes before release

    This might come across as ignorant, but I never really got behind what DUnitX does better than DUnit. For sure, it does things differently. But better? What are the advantages? Why should I consider migrating all DUnit test projects to DUnitX?
  21. Der schöne Günther

    How to properly detect name of exe (running app) in Windows 10

    What exactly is your question? You have a window handle (HWND) and you want to get the full path to the executable behind it?
  22. Der schöne Günther

    Complete Boolean Evaluation

    I am working on a legacy project which has it enabled. I did not dare to disable it, so all new units get a compiler directive to switch full bool eval off while you have to be extra careful and always keep in mind that full boolean eval is enabled when editing "old" units. Reason? I suppose there was none and "full Boolean evaluation" sounded better than "mediocre Boolean evaluation"
  23. Der schöne Günther

    FYI: Graph showing iOS crashes with recent Delphi versions

    It was some article that referred to a presentation from the early 90s, that's for sure. We once tried making a small application for iOS & Android, and yes, the application had so many fatal crashes with no way of debugging it that we finally gave up.
  24. Der schöne Günther

    FYI: Graph showing iOS crashes with recent Delphi versions

    Are there more information available about the crashes themselves? And didn't Delphi get famous by demonstrating how an unhandled access violation would just produce a messagebox and continued to work afterwards instead of bringing the whole app down?
  25. Der schöne Günther

    appending to a dynamic array

    The TStringHelper was designed for immutable strings. If I'm not mistaken, Strings on platforms such as iOS are immutable whereas they are still "copy on write" on Windows. All the TStringHelper methods return a new string instance.
×