4

I am working on a VCL (Delphi Win32) forms application platform with embedded scripting and would like to add debugging support. Scripting executes in the main VCL thread - scripts do direct UI manipulation and has some other legacy constraints keeping it in the UI thread.

The debugger UI needs to run in its own thread since the main UI thread will block on script breakpoints. It still needs to be in the same process for the thread-safe debugging component to work.

I tried to follow Blorgbeard's comment on https://stackoverflow.com/a/12505959/243144, but I am not sure if this is even possible with Delphi's VCL. (.NET creates a new ApplicationContext when passing a form to Application.Run) With the following Delphi, blocking of the main UI thread stops message processing on the second thread (and vice versa).

procedure TDebuggerThread.Execute;
begin
  CoInitialize(nil);

  FForm := TForm2.Create(nil);
  FForm.Show;
  Application.Run;
end;
Community
  • 1
  • 1
carlmon
  • 396
  • 6
  • 20
  • 3
    WinForms means .Net. Are you really using .Net with your Delphi project, or are you just using Delphi forms on Windows? – Rob Kennedy Feb 12 '13 at 20:03
  • Thanks I meant VCL forms, but I do use some .NET controls in my Delphi project via COM interop :). – carlmon Feb 12 '13 at 20:20
  • You may get this to work in one thread by using Fibers (see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682661%28v=vs.85%29.aspx). It will not work if your scripted code blocks on anything, but it will if you just want to single-step and visualize. Basically you need to turn your script breakpoints into switching the current fiber. I have used this to add single-stepping with visualization to image processing code using a COM library. – mghie Feb 12 '13 at 20:28
  • @mghie I don't think anyone in the world has ever managed to write a robust program using fibers. Not even MS could manage it for SQL server. – David Heffernan Feb 12 '13 at 20:39
  • @David: What can I say, the programs in question are robust enough, though, both for me and for the customer. It's not that hard to get right for this task, just two fibers and very defined switching points... – mghie Feb 12 '13 at 20:47
  • Delphi DLL with its own Tapplication copy? – Martin James Feb 12 '13 at 21:24
  • @mghie Beyond Compare uses fibers in its main loop and I do *not* recommend it unless you have control over the computer it's running on. Depending on how you're using them, any application that uses SetWindowsHookEx for a global hook can introduce crashes into your app. Logitech's SetPoint mouse driver is the most prevalent one that does that, and we have to switch to an alternate fiber library on systems where it's installed. – Zoë Peterson Feb 12 '13 at 22:17
  • @Craig: Thanks for the warning - I didn't know that and have never experienced anything like it. Luckily these are programs running on tightly controlled company-internal systems used nearly exclusively for them. Situation may be different for carlmon, I agree. – mghie Feb 13 '13 at 04:43

2 Answers2

6

Delphi forms are single-thread only. Any descendant of TControl, including TForm, must only be accessed from the main UI thread. Never call any TApplication method on anything but the main thread.

You're of course allowed to create other windows that are tied to different threads. You just can't use the VCL UI elements in those threads. Instead, you'll use CreateWindow to create the main window and any controls on it. You'll write a window procedure to handle any messages sent to those windows. You'll handle control-notification messages in the parent's window procedure rather than the child's.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Thanks Rob, is there a possibility of getting VCL forms to work with COM in a different thread? I _can_ go out of process or just synchronise all my scripting access to the UI and get it to run in a background thread, but hoped for an easier solution. – carlmon Feb 12 '13 at 20:24
  • 3
    No. As I said, VCL classes only work on the main UI thread. COM has nothing to do with it. – Rob Kennedy Feb 12 '13 at 20:27
5

One of the constraints of the VCL is that all interaction with GUI controls must be performed on the main thread. There's no way to circumvent that.

If you want to show debugger GUI in a separate thread, using VCL, your only option is to use an out-of-process solution. In other words, run your debugger in a different process, and use IPC to communicate between the two processes.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • There is an in-process way. That can be achieved by using a DLL for the other "VCL thread". The DLL must contain its own RTL and VCL. So that the DLL's RTL/VCL doesn't know the EXE's RTL/VCL. If you want more than 2 threads you need another DLL, you can't load one DLL twice into memory (without writing your own DLL loader) – Andreas Hausladen Feb 13 '13 at 11:49
  • @AndreasHausladen The easy way to get another DLL is to make a copy to a different filename and that forces the loader to treat it differently. – David Heffernan Feb 13 '13 at 12:17