Link to home
Start Free TrialLog in
Avatar of FMJMEE
FMJMEE

asked on

threads in C++ builder 3

I want to execute  MyPrint(){some very basic but large data} when I press abutton, and I want to do it with a thread so I do have to wait to the printer to finish their work.
I want to use the File|new...|thread Object of IDE. I got

__fastcall ThPrint::ThPrint(bool CreateSuspended)
 : TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall ThPrint::Execute()
{
    //---- Place thread code here ----
   Form1->Synchronize(MyPrint()); ?
}
 where do I start the thread?
 do I need to use new?
 where do I place the Resume?
 Do I have to use TThreadMethod?

Thank you very much for your help, any comments are welcomed.
Avatar of AlexVirochovsky
AlexVirochovsky

   TThread cannot be used as-is.  You must derive a class from TThread
    as demonstrated in example TThreads. Next is snippet of code
(file sortthd.h poject TThreads):
//----------------------------------------------------------------------------
//Borland C++Builder
//Copyright (c) 1987, 1997 Borland International Inc. All Rights Reserved.
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#ifndef SortThdH
#define SortThdH
//----------------------------------------------------------------------------
#include <ExtCtrls.hpp>
#include <Graphics.hpp>
#include <Classes.hpp>
#include <System.hpp>
//----------------------------------------------------------------------------
extern void __fastcall PaintLine(TCanvas *Canvas, int i, int len);
//----------------------------------------------------------------------------
class TSortThread : public TThread
{
private:
      TPaintBox *FBox;
      int *FSortArray;
      int FSize;
      int FA;
      int FB;
      int FI;
      int FJ;
      void __fastcall DoVisualSwap(void);

protected:
      virtual void __fastcall Execute(void);
      void __fastcall VisualSwap(int A, int B, int I, int J);
      virtual void __fastcall Sort(int *A, const int A_Size) = 0;
      
public:
      __fastcall TSortThread(TPaintBox *Box, int *SortArray,
          const int SortArray_Size);
};
//----------------------------------------------------------------------------
class TBubbleSort : public TSortThread
{
protected:
      virtual void __fastcall Sort(int *A, const int A_Size);
public:
      __fastcall TBubbleSort(TPaintBox *Box, int *SortArray,
          const int SortArray_Size);
};
//----------------------------------------------------------------------------
class TSelectionSort : public TSortThread
{
protected:
      virtual void __fastcall Sort(int *A, const int A_Size);
public:
      __fastcall TSelectionSort(TPaintBox *Box, int *SortArray,
          const int SortArray_Size);
};
//----------------------------------------------------------------------------
class TQuickSort : public TSortThread
{
protected:
      void __fastcall QuickSort(int *A, const int A_Size, int iLo,
        int iHi);
      virtual void __fastcall Sort(int *A, const int A_Size);
public:
      __fastcall TQuickSort(TPaintBox *Box, int *SortArray,
          const int SortArray_Size);
};
//----------------------------------------------------------------------------
#endif
If you want full code of Project in BCB4, write you EMail
Alex 
Avatar of FMJMEE

ASKER

How can I do some printing in a thread?
I already have that example.
Correction!. My question say "..so I do have to wait for the printer... ", must say "so I do NOT have to wait for the printer " I will appreciate any comments
 Thank you very much for your help!
Next is answer, how to use TThread class in BCB3(not 4!)
You must use this code and inplement you function Run(),
as can be Print.

Question and Answer Database

FAQ2373C.txt   TThread Run () in OWL
Category   :OWL
Platform    :All
Product    :C++Builder  3.x

Question:
How to use Run () in a TThread in OWL?

Answer:
There is a missing function in the docs:

virtual int Run();

Basically, it goes like this:

a) You derive from TThread and override Run().  Any code executing from this
Run() is in the new thread owned by the TThread class.

b) When you call Start() will your new thread object, TThread creates a new
windows thread and makes it call your Run() function

c) You have to be aware of the valid states and state transitions.  For
example, when you create a new TThread object, it is in the TThread::Created
state.  The only valid transition is to TThread::Running (this is done by
calling Start()).  So in other words, you can't create a TThread object and
not call its Start(). If you try to delete this object before calling
Start(), it will throw an exception.  Also, the new thread is done when you
return from Run() or when you call Exit() (i think).  Basically, you must
call Start() exactly once for each instance of TThread.  This means that you
must call Start() before deleting the object and you can only can Start()
once during the lifetime of the object.  All this kind of stuff is in the
docs, but I thought I would mention it anyway.

If you want a slick way of controlling a thread without being required to
derive from it, check out the code below.

Basically, any class that needs multithreading, just derive from Runnable
and override int Run().  When you're ready, you can create a new ThreadEx
object like:


// assuming 'this' is an instance of an object derived
// from Runnable
//
ThreadEx* mythread = new ThreadEx(this);
myThread->Start();

you now have an object that can USE threads without being a thread object
itself and without having to create a separate DoSomethingInAnotherThread
class derived from TThread every time you need another functionality in
separate thread.  The object using a ThreadEx can create a new thread, run
it, delete it, create another, run it, delete it ....

Here is the code:


//
// declaration
//
class ThreadEx;

class Runnable {
  public:
    Runnable();

  protected:
    virtual int Run() = 0;

    friend ThreadEx;
};

class ThreadEx : public TThread {
  public:
    ThreadEx(Runnable* runnable);
    virtual ~ThreadEx();

    int Run();
    bool ShouldTerminate();
    TThread::THandle Start();
    TThread::THandle GetHandle();
    void Kill();


  protected:
    Runnable* runnable;
    TThread::THandle threadHandle;
};



//
//
// Runnable implementation
//
Runnable::Runnable() {
}

//
//
// ThreadEx implementation
//
ThreadEx::ThreadEx(Runnable* runnable) {
  if(runnable == NULL)
    xmsg("ThreadEx: Invalid Runnable").raise();

  this->runnable = runnable;
}

ThreadEx::~ThreadEx() {
  switch(GetStatus()) {
    case Created:  Start();
    case Suspended:  Resume();
    case Running:  TerminateAndWait(5000);
          if(GetStatus() != Finished)
                       Kill();
                     break;
  }
}

TThread::THandle ThreadEx::Start() {
  threadHandle = TThread::Start();
  return threadHandle;
}

TThread::THandle ThreadEx::GetHandle() {
  return threadHandle;
}

//
// Avoid using Kill().  It will obliterate the thread and any resources that
were allocated by
// your code will not be freed.
//
void ThreadEx::Kill() {
  ::TerminateThread(threadHandle, 0);
}

bool ThreadEx::ShouldTerminate() {
  return TThread::ShouldTerminate();
}

int ThreadEx::Run() {
  return runnable->Run();
}

I hope, it helps. Alex
Avatar of FMJMEE

ASKER

Sorry! I can´t get the point, the code is confusing, and I don´t see anything better than what I already have.
Thanks.
This article is the reply of Borland
Team. Thus all reproachs are to
Borland! For me text is clear, but
I have BCB4 and can't test it.
Sorry, but i can't more help you.
Alex
ASKER CERTIFIED SOLUTION
Avatar of Roger Alcindor
Roger Alcindor

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of FMJMEE

ASKER

Well done, how about passing a parameter (integer) to:  TForm1::MyPrint(), is it possible?

Thank you very much
Thanks for the points. In answer to your question regarding passing a parameter, Yes, it is possible to pass an integer parameter; just declare it in the member function prototype as normal.

bool TForm1::MyPrint(int param)
{// pseudo - code
   if(printingnotstatrted)
   {
     startprinting process..
     using param as needed ..
     return false;
   }
   else
   if(printingfinished)
       return true;
   else
       return false;
}

Avatar of FMJMEE

ASKER

I mean at Synchronize(DoPrinting);
because I get an error message here if I use : Synchronize(DoPrinting(4));
any hint?

Thanks for your time, best regards
               
Unfortunately, you can't pass a parameter in the Synchronize() function. You may however, declare and use a variable in your ThPrint class and have your DoPrinting() function use it. You could set the variable either in your Execute() function, in your ThPrint constructor or even by adding a public memeber funtion to ThPrint such as
void ThPrint::SetParameter(int p){param = p};

Good luck & merry Xmas.