TThread is not a normal class

 Delphi, GExperts  Comments Off on TThread is not a normal class
Apr 222018
 

In Delphi, threads have traditionally been implemented as classes descending from TThread. While there have been quite a few improvements to multithreading, TThread is still the most compatible way. But TThread is not a normal class.

In a normal class, the constructor and destructor usually look like this:

constructor TSomeClass.Create;
begin
  inherited;
  FSomeList := TStringList.Create;
end;

destructor TSomeClass.Destroy;
begin
  FreeAndNil(FSomeList);
  inherited;
end;

In the constructor, we first call inherited and afterwards add code to initialize additional fields of the object. In the destructor we first free any fields of the object and only then call inherited for the ancestor class to free its resources.

Now, TThread is peculiar because its constructor and destructor are usually executed in the program’s main thread, while its Execute method is executed in a different thread. But, when is that thread started? It’s started when you call the inherited constructor. So any initialization that thread needs must be done before calling inherited!

Edit: Several people have pointed out that my claim is somewhat “outdated”, where “outdated” means that since Delphi 6 the thread is started in the AfterConstruction method rather than in Create. In Delphi 5 it was the last command in TThread.Create (here is a probably not authorized copy of that code, search for “Delphi5Thread” on the page).

What I wrote about the destructor is still true though.

constructor TMyThread.Create;
begin
  FSomeList := TStringList.Create;
  inherited;
end;

Otherwise the field FSomeList might not have been initialized when the thread tries to access it.

Similar, if the thread is still running, you must be sure that all the resources it requires are available until it has stopped. So, the first thing would be to tell the thread to terminate, wait for it to actually do that and only then destroy it.

MyThread := TMyThread.Create;
// do something else while the thread does its thing
// ...
// now tell it to terminate (this is standard way of doing that
// but it might not be the best)
MyThread.Terminate;
// and destroy it
FreeAndNil(MyThread);

But that’s only half of it. The destructor must also take care not to destroy anything the thread still needs:

destructor TMyThread.Destroy;
begin
  // first, wait for the thread to terminate
  // (the inherited destructor calls WaitFor)
  inherited;
  // now the thread has definitely terminated, so we can free the resources
  FreeAndNil(FSomeList);
end;

Beware: These are just the simplest precautions to take when programming with multiple threads. As they say: "Creating threads is easy but multithreading is hard." If you can, use a library that does the ground work for you.

Why do I blog about this? I just fixed a few Access Violations in GExperts that were caused by TThread objects implemented the wrong way. (I have no idea who did that, it’s quite possible that I am myself to blame for that.)

GExperts Usage Statistics

 Delphi, GExperts  Comments Off on GExperts Usage Statistics
Mar 302018
 

Have you ever wondered which functions of GExperts you have used the most? Or how often at all? How much time it has saved you?

Now you can find out: I just added Usage Statistics to GExperts which tells you exactly how often you have called each of the experts, in the current session and also in total (data between sessions is saved in the registry). Currently it can be accessed via a button in the Configuration dialog, but I am not sure yet where to put it.

So far, it has told me nothing new: My most used functions are, in descending order:

But this is just after a few minutes of actually using GExperts after I have added the statistics, so there might still be some surprises. I am wondering about the Code Proofreader for example.

I plan to do a new release shortly (oh my, the last one is over a year old!), maybe even during the Easter holidays, but don’t hold your breath. In the meantime, you can simply compile your own GExperts dll.

Fixing the Delphi 10.2.2 February 2018 Patch

 Delphi, GExperts  Comments Off on Fixing the Delphi 10.2.2 February 2018 Patch
Feb 172018
 

UPDATE: The problem was that I was using Delphi 10.2.2 build 1978. Apparently I have missed an update in December 2017 to build 2004. I have downloaded and installed the new version, and now the patch worked fine.

I hereby apologize for being stupid, because it clearly says in the description:

This patch for RAD Studio 10.2.2 (build 2004 — it won’t work on build 1978) resolves some compatibility issues in the RTL and fixes a problem with Android animations. It is designed to be installed only on top of an existing RAD Studio 10.2.2 Tokyo installation.

(emphasis mine)

I was so sure to be running the latest version that I didn’t even check. Sorry about causing so much fuss.

I’ll leave the rest of the blog post unchanged just in case anybody is googling for some of the key words and to remind me to check first and complain later.

After I reported the problem with the Delphi 10.2.2 February 2018 Patch, Embarcadero first removed the download and has now released a new installer. Unfortunately this new patch might have solved some other problems, but it didn’t solve mine. I did a complete uninstall of Delphi 10.2.2 (I even removed all directories and files that the uninstall left behind) and a new installation from my DVD followed by applying the new patch. I could still not compile GExperts and the simple test program I described in the steps for the bug report did not compile either. (Guess what: Embarcadero apparently never actually tried to reproduce my problem, but the ticket was closed anyway.). I don’t know what exactly they think they fixed, but they didn’t fix the problem I reported which is:

RAD Studio 10.2.2 Tokyo February 2018 Patch breaks “Link with rutime packages”

  1. Create a new VCL project
  2. Open project options
  3. Select Packages -> Runtime Packages
  4. Set “Link with runtime packages” to true
  5. Close dialog with OK
  6. Compile the project
  7. -> Error

Today I tried to find out what the problem was and how to fix it. It turned out to be actually quite simple:

They updated the packages rtl.bpl and fmx.bpl together with their corresponding .dcp files. Since the .dcp files contain some versioning information the packages that use these packages (e.g. vcl.bpl which uses rtl.bpl) were no longer compatible with the new packages and the compiler complained about this.

So, the fix for this would be to recompile all the packages depending on rtl.bpl and fmx.bpl, but since I don’t have all the sources required for that, I couldn’t do that (but Embarcadero should).

What I did instead was replacing the .dcp files in libs\win32\debug and libs\win32\release with the .bak files that the Patch created. Afterwards, GExperts compiled again. And since probably the interface of the bpl files didn’t change, I don’t expect any problems. But of course, I can’t guarantee this. So, if you follow my example, you might still run into problems and, No, I won’t fix your computer. 😉

GExperts Bugfixes

 GExperts  Comments Off on GExperts Bugfixes
Dec 302017
 

The Unicode issues in GExperts just don’t end. Today I fixed three of them:

procedure bla;
begin
  SomeVar := 3245;
  // german description with some äöüß to SomeVar
  SomeVar := 123;

  SomeQuery.FieldByName('GermanWordWithäöüß').AsString := 'some value';
end;

(Yes, I know, this doesn’t compile.)

  • Move the cursor to the first occurrence of SomeVar and press Ctrl+Alt+Down. The cursor jumps to the middle of the next Occurrence of SomeVar instead of the start of the identifier.
  • Move the cursor to the opening parenthesis after FieldByName and press Ctrl+Alt+Right. The cursor moves to somewhere in AsString rather than the closing parenthesis.
  • Move the cursor to the closing parenthesis and press Ctrl+Alt+Left. You get the error that AsString is not a valid delimiter

They were caused by the two byte UTF-8 characters in the respective lines which threw off the column index.

And if that wasn’t enough I also fixed some bugs in the Grep history list which could cause an Access Violation, infinite loop or wrong check marks in the Open dialog.

All these were reported by Konstantin Tkachenko who also included some patches which fixed them. Unfortunately he could only test them in Delphi 2010 so they worked for Delphi 2007+ but not for Delphi 6 and 7. They were valuable nonetheless. Thanks Konstantin!

Also, Achim Kalwa, who already contributed quite a few patches to GExperts, sent me some more this week:

  • Remove the ugly “(S+C+x)” suffixes in the Project Options dialog and replace them with a hint.
  • Sort the component names by tab order in the Copy Component Names expert.
  • Shortcuts for Add/Remove/Default buttons in the Editor Popup menu configuration dialog as well as sorting the list of experts alphabetically.

I’m no longer accepting GExperts donations via Flattr

 GExperts  Comments Off on I’m no longer accepting GExperts donations via Flattr
Oct 212017
 

Flattr have changed their terms an conditions. Since I haven’t received a single cent via Flattr, I really can’t be bothered what exactly they have changed and whether that’s good or bad for me personally. So I have closed that account for good. That leaves only PayPal, if you want to make a donation to GExperts. Sorry, if that’s an inconvenience. And please remember that I’d prefer you to contribute to GExperts in one of the other means described on that page than money.

Enhancements to GExperts Grep

 GExperts  Comments Off on Enhancements to GExperts Grep
Oct 142017
 

Jeroen has submitted two enhancements to GExperts:

Thanks!

I am still working on the refactoring for the IDE form enhancements, but progress is slow, so the next release will probably take a while.

Some documentation on the internals of GExperts

 Delphi, GExperts  Comments Off on Some documentation on the internals of GExperts
Aug 202017
 

I have started to write some documentation on the internal workings of GExperts. For now, it covers only a very small part of the IDE form enhancements that GExperts provides. It is meant mostly for myself to get an overview of that part of the tool which has grown too large to understand at a single glance. But it might also help if somebody wants to contribute to that part.

How I used some more of the money donated to GExperts

 Delphi, GExperts  Comments Off on How I used some more of the money donated to GExperts
Aug 122017
 

Donations for GExperts keep coming in. It’s more a trickle than a flood but hey, I’m not in it for the money. And please remember that I prefer other kinds of contributions over money.

I have used that money in turn for donations to

I would have liked to also donate to PuTTY and FileZilla but I found no way to do it.

(Yes, there is a donate link on the FileZilla SourceForge page but it doesn’t work.)

Changing the order of TabSheets in a PageControl in Delphi

 Delphi, GExperts  Comments Off on Changing the order of TabSheets in a PageControl in Delphi
Jul 302017
 

The method of changing the order of the TabSheets in a PageControl in Delphi is not obvious. Apparently there is no drag and drop support (at least not in Delphi 2007). You have to change the PageIndex property. So, if you want to insert a new page, add it and then change its PageIndex to the insert position.

I smell an opportunity for a new GExperts Expert. Any takers?

EDIT: As Moreno Zenaro pointed out in a comment to my Google+ post, there is actually a GUI way of changing the order: Drag the TabSheet in the structure view.

Bug in Macro Template expert fixed, yet another Unicode issue in GExperts

 Delphi, GExperts  Comments Off on Bug in Macro Template expert fixed, yet another Unicode issue in GExperts
Jul 292017
 

As I stated before I prefer good bug reports on GExperts over money any time. Philip von Melle kept testing and providing feedback even after I thought the issue was already solved.

The issue was that a Macro Template

(%SELECTION)

used on this code

// öäüß

procedure TForm1.FormCreate(Sender: TObject);
begin
  ShowMessage('TEST');
end;

while TEST was selected
generated code like this

// öäüß

procedure TForm1.FormCreate(Sender: TObject);
begin
  ShowMessage(''); (TEST)
end;

The reason again was improper use of positions and offsets into the editor buffer in conjunction with some Unicode characters above the code. So the insert position was calculated by 4 bytes too high, hence the macro code was inserted 4 characters behind the start of the original selection.