BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

VCL-Component-Acces from Thread

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Language C++)
View previous topic :: View next topic  
Author Message
iwl
Guest





PostPosted: Mon Dec 11, 2006 4:39 pm    Post subject: VCL-Component-Acces from Thread Reply with quote



Hello,

I have to acces several Visual components from a thread (e.g.
Trackbars)
Trackbar->Postition=xyz etc.
As far I red this is not safe.
Using syncronize is very unconfortable for me, when I have to write a
func for every thing I wan't to do passable to Syncronize.
Is there some bether way something I can call befor
Trackbar->Postition=xyz and after that?
I read some thing about Critical section but as far I understand this
only works also having such a section in the VCL-main-thread I can't
change.
Back to top
Danzer
Guest





PostPosted: Mon Dec 11, 2006 9:30 pm    Post subject: Re: VCL-Component-Acces from Thread Reply with quote



iwl wrote:
Quote:
Hello,

I have to acces several Visual components from a thread (e.g.
Trackbars)
Trackbar->Postition=xyz etc.
As far I red this is not safe.
Using syncronize is very unconfortable for me, when I have to write a
func for every thing I wan't to do passable to Syncronize.
Is there some bether way something I can call befor
Trackbar->Postition=xyz and after that?
I read some thing about Critical section but as far I understand this
only works also having such a section in the VCL-main-thread I can't
change.


Post a message in your thread to the owner of the Trackbar and call
Application->ProcessMessages. Update the Trackbar in the message handler.

Danzer
Back to top
Clayton Arends
Guest





PostPosted: Tue Dec 12, 2006 12:23 am    Post subject: Re: VCL-Component-Acces from Thread Reply with quote



Quote:
As far I red this is not safe.

That is correct. VCL controls are not thread-safe.

Quote:
I read some thing about Critical section but as far I understand this
only works also having such a section in the VCL-main-thread I can't
change.

As you have mentioned TCriticalSection will not work for updating VCL
controls from a thread. The only way to update a VCL control is in the
context of the main thread.

To solve your problem you can use what Danzer suggested (though, you don't
need the Application->ProcessMessages() call). The Windows message queue is
thread-safe. If you'd like to get a little fancier try the following code:

// H file
#include <Classes.hpp>
#include <ComCtrls.hpp>
#include <Controls.hpp>
#include <Forms.hpp>
#include <StdCtrls.hpp>
#include <SyncObjs.hpp>

static const UM_UPDATEPROGRESSBAR = WM_USER + 100;

class TTestThread : public TThread
{
public:
struct TMessageData
{
unsigned Position;
unsigned Max;
};

private:
TCriticalSection* fDataSync;
TMessageData fMessageData;
HANDLE fOwnerHandle;

protected:
virtual void __fastcall Execute();

public:
TTestThread(HANDLE OwnerHandle);
__fastcall ~TTestThread();

TMessageData GetMessageData();
};

class TForm1 : public TForm
{
__published:
TProgressBar *ProgressBar1;
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
private:
TTestThread* Thread;

void __fastcall ThreadTerminate(TObject* Sender);

protected:
void UmUpdateProgressBar(TMessage& Message);

BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(UM_UPDATEPROGRESSBAR, TMessage,
UmUpdateProgressBar)
END_MESSAGE_MAP(TForm)

public:
__fastcall TForm1(TComponent* Owner);
};


// CPP file
TTestThread::TTestThread(HANDLE OwnerHandle)
: TThread(true), fOwnerHandle(OwnerHandle)
{
fDataSync = new TCriticalSection;
}

__fastcall TTestThread::~TTestThread()
{
delete fDataSync;
}

void __fastcall TTestThread::Execute()
{

// Initialize the position and range of the progress
fDataSync->Acquire();
fMessageData.Position = 0;
fMessageData.Max = 100000;
fDataSync->Release();
::PostMessage(fOwnerHandle, UM_UPDATEPROGRESSBAR, 0, 0);

for (int index = 0; index < 100000; ++index)
{
// a little delay to keep things from happening all at once
// (Sleep takes too long)
for (int index = 0; index < 10000; ++index);

// Update the progress position
fDataSync->Acquire();
fMessageData.Position = index;
fDataSync->Release();
::PostMessage(fOwnerHandle, UM_UPDATEPROGRESSBAR, 0, 0);
}
}

TTestThread::TMessageData TTestThread::GetMessageData()
{
fDataSync->Acquire();
TMessageData result = fMessageData;
fDataSync->Release();
return result;
}


__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
if (Thread)
return;

Thread = new TTestThread(Handle);
Thread->FreeOnTerminate = true;
Thread->OnTerminate = &ThreadTerminate;
Thread->Resume();
}

void __fastcall TForm1::ThreadTerminate(TObject* Sender)
{
Thread = NULL;
}

void TForm1::UmUpdateProgressBar(TMessage& Message)
{
if (!Thread)
{ // Thread is completed
ProgressBar1->Position = ProgressBar1->Max;
return;
}

{ // Remove any other queued UM_UPDATEPROGRESSBAR messages
MSG msg;
while (PeekMessage(&msg, Handle,
UM_UPDATEPROGRESSBAR, UM_UPDATEPROGRESSBAR, PM_REMOVE));
}

TTestThread::TMessageData data = Thread->GetMessageData();
ProgressBar1->Position = data.Position;
ProgressBar1->Max = data.Max;
}

The purpose of this code is to not block either thread when the progress bar
needs to update. It also removes excess duplicate messages from the queue
(there might be a more Windows way of doing that, I'm not sure). To test
this create a new application, add a button and a progress bar.

There are other ways you can pass data from the worker thread to the main
thread. If you have a lot of data that you do not want to get copied then
you can pass by pointer but you'll need to have two accessor methods. One
acquires the critical section and one releases it. Just make sure you sync
up the reads and writes using a TCriticalSection or a
TMultiReadExclusiveWriteSynchronizer and always make sure that VCL control
updates are performed in the context of the main application thread.

HTH,
- Clayton
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Language C++) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.