 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Jeti Guest
|
Posted: Tue Mar 22, 2005 2:53 pm Post subject: Is the Invalidate() Method of a TControl (as TMemo) safe thr |
|
|
In my BCB6 project, I have in addition to the main/Vcl thread,
a secondary thread that isn’t a Borland Thread
so I cannot use the Sinchronize() method of Tthread.
I want the secondary thread to log its output also on a Tmemo component of the main form.
So with the wizard help, I created and installed a new component TWriterMemo with ancestor type “Tmemo”,
and I added :
the public method Write(),
the protected member std::list<std::string> m_list;
and I Overrided the virtual method Update()
// ================== TwriterMemo.h ================
class PACKAGE TWriterMemo1 : public TMemo, public IWriter
{
protected: // User declarations
std::list<std::string> m_list;
TCriticalSection *m_cs;
public: // User declarations
void Write(const std::string msg);
virtual void __fastcall Update(void);
private:
protected:
public:
__fastcall TWriterMemo1(TComponent* Owner);
__fastcall ~TWriterMemo1();
__published:
};
// ================== TwriterMemo.cpp ================
void TWriterMemo1::Write(const std::string msg)
{
m_cs->Acquire();
m_list.push_back(msg);
m_cs->Release();
Repaint();
}
//---------------------------------------------------------------------------
void __fastcall TWriterMemo1::Update(void)
{
m_cs->Acquire();
while (!m_list.empty())
{
std::string str = m_list.front();
m_list.pop_front();
Lines->Add(str.c_str());
}
m_cs->Release();
}
Naturally the secondary thread knows my custom memo and invokes the method Write(string s) that stores the string and invalidates the component.
Is this approach correct and thread safe?
If not, could you suggest me a good soluction?
Thanks.
Jeti
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Tue Mar 22, 2005 9:18 pm Post subject: Re: Is the Invalidate() Method of a TControl (as TMemo) safe |
|
|
"Jeti" <massimo.jentile (AT) seleniacomms (DOT) com> wrote
| Quote: | In my BCB6 project, I have in addition to the main/Vcl
thread, a secondary thread that isn't a Borland Thread
so I cannot use the Sinchronize() method of Tthread.
|
You can post messages to the main thread using PostMessage(), SendMessage(),
PostTheadMessage(), etc.
| Quote: | I want the secondary thread to log its output also on a Tmemo
component of the main form.
|
You can use SendMessage() to send a custom message to the main thread,
passing it the string pointer to display.
| Quote: | m_cs->Acquire();
m_list.push_back(msg);
m_cs->Release();
|
push_back() can potentially throw an exception. You should wrap the
Acquire() and Release() calls with exception handling to ensure that you
always release the critical section even when an error occurs.
Repaint() is not thread-safe.
| Quote: | void __fastcall TWriterMemo1::Update(void)
|
You are misusing Update(). It is meant to be used to process pending
painting messages only. Not for altering the component's contents.
| Quote: | Is this approach correct and thread safe?
|
No on both accounts.
| Quote: | If not, could you suggest me a good soluction?
|
You don't need a new component at all. Use a custom message instead, ie:
#define APPWM_LOG_MSG (WM_APP + 100)
void __fastcall TForm1::WndProc(TMessage &Message)
{
if( Message.MSg == APPWM_LOG_MSG )
{
Memo1->Lines->Add(reinterpret_cast<char*>(Message.LParam));
Message.Result = 1;
}
else
TForm::WndProc(Message);
}
DWORD WINAPI MyThreadFunc(LPVOID lpData)
{
//...
std::string msg = "...";
::SendMessage(Application->MainForm->Handle,
APPWM_LOG_MSG, 0, reinterpret_cast<LPARAM>(msg.c_str()));
//...
}
If you don't want to reference the VCL at all in your thread code, or if you
want to send the log messages to a different TForm, then store the target
HWND somewhere in memory that the thread code can reach, such as by wrapping
the thread in a class and using the thread's LPVOID parameter to access that
class, so that the target HWND can be a member of that class. For example:
class MyThreadClass
{
private:
HANDLE FThread;
DWORD FThreadID;
HWND FLogWnd;
CRITICAL_SECTION LogWndCS;
//...
static DWORD WINAPI ThreadFunc(LPVOID lpData);
struct CSLock
{
LPCRITICAL_SECTION lpcs;
CSLock(LPCRITICAL_SECTION cs);
~CSLock();
};
public:
MyThreadClass();
~MyThreadClass();
HWND getLogWnd();
void setLogWnd(HWND AWnd);
void LogMsg(const std::string &msg);
void Start();
//...
};
MyThreadClass::CSLock::CSLock(LPCRITICAL_SECTION cs)
: lpcs(cs)
{
::EnterCriticalSection(lpcs);
}
MyThreadClass::CSLock::~CSLock()
{
::LeaveCriticalSection(lpcs);
}
MyThreadClass::MyThreadClass()
{
InitializeCriticalSection(&LogWndCS);
FLogWnd = NULL;
//...
}
MyThreadClass::~MyThreadClass()
{
//...
DeleteCriticalSection(&LogWndCS);
}
HWND MyThreadClass::getLogWnd()
{
CSLock lock(&LogWndCS);
return FLogWnd;
}
void MyThreadClass::setLogWnd(HWND AWnd)
{
CSLock lock(&LogWndCS);
FLogWnd = AWnd;
}
void MyThreadClass::LogMsg(const std::string &msg)
{
HWND hwnd = getLogWnd();
if( hwnd != NULL )
::SendMessage(hwnd, APPWM_LOG_MSG, 0,
reinterpret_cast<LPARAM>(msg.c_str()));
}
void MyThreadClass::Start()
{
if( FThread == NULL )
FThread = ::CreateThread(NULL, 0, ThreadFunc, this, 0,
&FThreadID);
}
DWORD WINAPI MyThreadClass::ThreadFunc(LPVOID lpData)
{
MyThreadClass *pThis = static_cast<MyThreadClass*>(lpData);
//...
pThis->LogMsg("whatever");
//...
}
class TSomeForm : public TForm
{
private:
MyThreadClass Thread;
protected:
virtual void __fastcall CreateWnd();
virtual void __fastcall DestroyWnd();
//...
};
void __fastcall TForm1::CreateWnd()
{
TForm::CreateWnd();
Thread.setLogWnd(Handle);
}
void __fastcall TForm1::DestroyWnd()
{
Thread.setLogWnd(NULL);
TForm::DestroyWnd();
}
Gambit
|
|
| Back to top |
|
 |
Jeti Guest
|
Posted: Thu Mar 24, 2005 1:38 pm Post subject: Re: Is the Invalidate() Method of a TControl (as TMemo) safe |
|
|
Thanks a lot for your help, I’ll follow your suggestion at once !
Just a little info to be coherent with the subject:
is the Invalidate() method (as the Repaint) not thead-safe ?
Thanks
Jeti
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|