12

Can someone post the simplest thread example for Delphi 2010 that for example puts some text into a memo when button clicked? With implementation and all. Thanks.

Update: Ok, just a simple thread that does something. No need for a memo. Thanks.

RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • 5
    Why would you want a thread to put text in a memo? In fact that's just about the worst example imaginable because UI code all needs to run in the main thread. – David Heffernan Mar 08 '11 at 13:44
  • 4
    @David - it's useful for things like reporting the status to the user. i.e. a thread runs search the disk for malware. It has to report progress, "hits", etc., back to the main thread. It would likely need to do that via Synchronize. – Chris Thornton Mar 08 '11 at 13:48
  • 2
    @Chris I tend to avoid `Synchronize` which is quite heavyweight and solve the problem differently. – David Heffernan Mar 08 '11 at 13:50
  • 3
    @David, overuse of Synchronize can negate the benefits of using a thread in the first place. Used appropriately, it's the usual and accepted practice, as far as I know. And it's used by the demo that I cited. – Chris Thornton Mar 08 '11 at 13:53
  • Simplest and Thread in one sentence usually adds a negation, especially when putting Synchronize in as well. – Jeroen Wiert Pluimers Mar 08 '11 at 13:56
  • @Chris I know. That's why I avoid it. – David Heffernan Mar 08 '11 at 14:02
  • 4
    This question is close to useless without saying *why* you want to do this. It makes all the difference in the world! Answers provided without the specific context of what you're doing may prove to be unhelpful to you in the long run. – Craig Stuntz Mar 08 '11 at 14:28
  • 1
    Hey, nobody mentioned OmniThreadLibrary yet did they? It's nicer than working in native TThread, and has lots of demos. – Warren P Mar 08 '11 at 20:04

4 Answers4

13

There's a nice thread demo, including GUI/Synchronize, that ships with Delphi. In D2005, it's in: C:\Program Files\Borland\BDS\3.0\Demos\DelphiWin32\VCLWin32\Threads

Chris Thornton
  • 15,620
  • 5
  • 37
  • 62
11

Simplest example I can imagine: (Suppose you have Memo1 on Form1)

procedure TForm1.Button1Click(Sender: TObject); 
begin   
  TThread.CreateAnonymousThread(procedure
      var
        slThread: TStringList;
        i: Integer;
        begin
          //do something in thread
          slThread := TStringList.Create;
          try
            for i := 0 to 100 - 1 do
            begin
              slThread.Add(Format('Value %D',[i]));
            end;

            //update gui
            TThread.Synchronize(nil, procedure
            begin
              Form1.Memo1.Lines.AddStrings(slThread);
            end);


          finally
            slThread.Free;
          end;


        end).Start;
end;

Although I won't recommend using it, because it has some disadvantages. It is better to descend your own TThread class but for your question this example fits nicely.

Linas
  • 5,485
  • 1
  • 25
  • 35
  • +1 for using anonymous methods and one of the latest versions of Delphi. – Allen Bauer Mar 08 '11 at 17:31
  • is the `nil,` after `TThread.Synchronize(` necessary here? (I don't think so) – mjn Mar 08 '11 at 18:40
  • It's TThread's instance parameter. Because we didn't declare it in this example, we must pass nil. – Linas Mar 08 '11 at 18:56
  • 1
    If you wrote anything like this and I was doing code-review, I would make you rewrite it. Of course, it's a demo for someone on stack overflow. We hope he/she doesn't just copy and paste this into their code though. There should be a "Don't use this code at all, ever, don't even think about it" tag we could place on answers without downvoting. Just ask the question: How do you debug and troubleshoot problems in this, when it grows to 5000 lines? – Warren P Mar 08 '11 at 20:03
  • 2
    Warren, the question was about the simplest example. Simplest in most cases isn't the best. On the other hand, TThread.CreateAnonymousThread is standard Delphi function which I guess is here for purpose. – Linas Mar 08 '11 at 21:51
  • 1
    OP asked for a simple example. Probably it is not a good idea to scare people away from Programming or Delphi – ssh Jan 13 '12 at 16:55
2

As it has been pointed out, creating a thread to update the GUI isn't a good design. It would be better to have your threads do some actual work, and allow the main thread update your display.

While Delphi also offers the TThread class to make creating/managing threads easier, you may also want to have a look at using Delphi's BeginThread function for executing simple threads. There is an example on the Delphi Basics website, which I have reproduced here:

// Full Unit code.
// -----------------------------------------------------------
// You must store this code in a unit called Unit1 with a form
// called Form1 that has an OnCreate event called FormCreate.

unit Unit1;

interface

uses
  Forms, Dialogs, Windows, SysUtils;

type
  TMsgRecord = record
    thread : Integer;
    msg    : string[30];
  end;
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  end;

var
  Form1: TForm1;

Implementation
{$R *.dfm}        // Include form definitions

ThreadVar         // We must allow each thread its own instances
                  // of the passed record variable
  msgPtr : ^TMsgRecord;

// Private thread procedure to show a string
function ShowMsg(Parameter : Pointer) : Integer;
begin
  // Set up a 0 return value
  Result := 0;

  // Map the pointer to the passed data
  // Note that each thread has a separate copy of msgPtr
  msgPtr := Parameter;

  // Display this message
  ShowMessagePos('Thread '+IntToStr(msgPtr.thread)+' '+msgPtr.msg,
                 200*msgPtr.thread, 100);

  // End the thread
  EndThread(0);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  id1, id2 : LongWord;
  thread1, thread2 : Integer;
  msg1, msg2 : TMsgRecord;

begin
  // set up our display messages
  msg1.thread := 1;
  msg1.msg    := 'Hello World';
  msg2.thread := 2;
  msg2.msg    := 'Goodbye World';

  // Start the first thread running asking for users first name
  thread1 := BeginThread(nil,
                         0,
                         Addr(ShowMsg),
                         Addr(msg1),
                         0,
                         id1);

  // And also ask for the surname
  thread2 := BeginThread(nil,
                         0,
                         Addr(ShowMsg),
                         Addr(msg2),
                         0,
                         id2);

  // Ensure that the threads are only closed when all done
  ShowMessagePos('Press this when other dialogs finished.', 200, 300);

  // Finally, tidy up by closing the threads
  CloseHandle(thread1);
  CloseHandle(thread2);
end;

end.

Here is also another example of how to use threads with parameters (using BeginThread).

Mick
  • 13,248
  • 9
  • 69
  • 119
  • Thanks, can you please post a simple example using a TThread class? –  Mar 08 '11 at 15:20
  • I don't think sample code should contain such problematic code like this (executing VCL GUI code in the context of secondary threads). – mghie Mar 09 '11 at 07:09
  • @mghie - I considered not posting it, but instead I called it out as a bad design in my comment. I'll leave it to others to decide if they want to make good/poor design decisions after I've informed them of the problem. – Mick Mar 09 '11 at 13:48
  • It's not obvious to me that your first sentence is meant to warn against your own code sample as well. And calling `ShowMessagePos()` like this is more than just badly designed, it's dangerous and wrong. – mghie Mar 09 '11 at 15:05
2

The best source of general information about threading in Delphi, bar none, can be found here - http://www.eonclash.com/Tutorials/Multithreading/MartinHarvey1.1/ToC.html. Have a look here before going anywhere else.

secelite
  • 1,353
  • 1
  • 11
  • 19
Misha
  • 1,816
  • 1
  • 13
  • 16