Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: CBXE8 - TIdUDPClient->SendBuffer() thread-safe in TTimer::OnTimer() ?



Permlink Replies: 4 - Last Post: Jul 29, 2015 6:43 PM Last Post By: GAI CHEW KAI
GAI CHEW KAI

Posts: 117
Registered: 7/25/14
CBXE8 - TIdUDPClient->SendBuffer() thread-safe in TTimer::OnTimer() ?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 27, 2015 9:04 PM
I am current using Embarcadero® C++Builder XE8 Version 22.0.19027.8951 and Indy 10.

TIdUDPClient->SendBuffer() raised exception error in TTimer::OnTimer() event.

The error message on the Android phone stated:

Access violation at address 4011BE52, accessing address A6022A38

Meanwhile at the CBXE8 IDE:

First chance exception at $53125BC8. Exception class Illegal instruction (4). Process MBXC.apk (8256)

NOTE: None of the exception is captured within the try catch statement.

Later, after the following references below:

http://www.devsuperpage.com/search/Articles.aspx?G=2&ArtID=2364
http://docwiki.embarcadero.com/CodeExamples/XE8/en/TThreadPriority_(C%2B%2B)

TIdUDPClient->SendBuffer() is now put under TThread::Execute(), only then the issues is resolved without any exception error with or without UDP server is running.

However, the thread source had a remark generated:

// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize( &UpdateCaption );
//
// where UpdateCaption could look like:
//
// void __fastcall TXThread::UpdateCaption ()
// {
// Form1->Caption = "Updated in a thread";
// }

QUESTIONS:

1. What is Synchronize() ? It can't be compiled for Android platform ( I omitted it to compile successfully ) ?

2. Somehow, how to ensure thread-safe in CBXE8 development for desktop and mobile, is there any reference or link information ?

3. For simplify reason, I often placed methods under OnTimer() but it will not work always and causing exception error, may I know what is the reason ?

Please advise.

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: CBXE8 - TIdUDPClient->SendBuffer() thread-safe in TTimer::OnTimer() ?[Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 28, 2015 8:39 PM   in response to: GAI CHEW KAI in response to: GAI CHEW KAI
GAI wrote:

TIdUDPClient->SendBuffer() raised exception error in TTimer::OnTimer()
event.

Then you are likely using it wrong. Please show your actual code.


That is a very poorly written example. Don't base your code on it.

TIdUDPClient->SendBuffer() is now put under TThread::Execute(),
only then the issues is resolved without any exception error *_with or
without UDP server is running_*.

I cannot say if that is a good or bad sign, without seeing your actual code.

1. What is Synchronize() ?

The TThread::Synchronize() method:

http://docwiki.embarcadero.com/Libraries/XE8/en/System.Classes.TThread.Synchronize

It can't be compiled for Android platform ( I omitted it to compile successfully
) ?

Yes, it can. The TThread class works the same on all platforms. What the
comment fails to say is that Synchronize() is a non-static method of TThread,
and is meant to be called inside of your overridden Execute() (and/or DoTerminate())
method.

3. For simplify reason, I often placed methods under OnTimer() but it
will not work always and causing exception error, may I know what is
the reason ?

Not without seeing your code. You are clearly doing something you should
not be doing.

--
Remy Lebeau (TeamB)
GAI CHEW KAI

Posts: 117
Registered: 7/25/14
Re: CBXE8 - TIdUDPClient->SendBuffer() thread-safe in TTimer::OnTimer() ?[Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 28, 2015 8:57 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
TIdUDPClient->SendBuffer() raised exception error in TTimer::OnTimer()
event.

Then you are likely using it wrong. Please show your actual code.
- The code is like below:

TIdBytes idbWrite;

// iResult is length of acBuf.

idbWrite.Length = iResult;

idbWrite = RawToBytes( acBuf, iResult );

try
{
udp->SendBuffer( idbWrite );
}
catch( const EIdSocketError& e )
{
}
catch( const Exception &e )
{
}
catch( ... )
{
}

NOTE: None of the exceptions under try-catch is captured.

Please advise.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: CBXE8 - TIdUDPClient->SendBuffer() thread-safe in TTimer::OnTimer()?[Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 29, 2015 12:25 AM   in response to: GAI CHEW KAI in response to: GAI CHEW KAI
GAI wrote:

- The code is like below:

That is not very useful. I would need to see that code in the context in
which it is being called. Since you are having errors related to threads
and timers, please show your thread code and timer code.

idbWrite.Length = iResult;

That allocation use redundant, as RawToBytes() will allocate and return a
new TIdBytes, replacing your allocated memory with its allocated memory.

idbWrite = RawToBytes( acBuf, iResult );

What is acBuf actually declared as?

NOTE: None of the exceptions under try-catch is captured.

Then the exception is not occuring inside of SendBuffer() to begin with.

--
Remy Lebeau (TeamB)
GAI CHEW KAI

Posts: 117
Registered: 7/25/14
Re: CBXE8 - TIdUDPClient->SendBuffer() thread-safe in TTimer::OnTimer()?[Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 29, 2015 6:43 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
> ... I would need to see that code in the context in which it is being called....
- Here is the source:

void __fastcall TfMain::tmOnTimer (TObject* Sender)
{
f_iOnNetworkUDPProc();
}

int TfMain::f_iOnNetworkUDPProc (void)
{
char acBuf[ OS_SZ_BF ]; // OS_SZ_BF...is 513
char acTmp[ OS_SZ_BF ];
char acStream[ OS_SZ_BF ];
char acData[ OS_SZ_BF ];
TIdBytes idbRead;
TIdBytes idbWrite;
String s;
UnicodeString us;
int iResult;
int len;
int n;
int x;

if( m_bUDPAck )
return OS_NOP;

if( !udp->Connected() )
{
return f_iOnNetworkUDPOpen();
}

if( !m_bUDPOpen )
return OS_ERR;

UDP_RCX:

idbRead.Length = udp->BufferSize;

try
{
len = udp->ReceiveBuffer( idbRead, 512 );
}
catch( const EIdSocketError& e )
{
}
catch( const Exception& e )
{
}
catch( ... )
{
}

if( len <= 0 )
goto UDP_TRX;

memset( acStream, 0x00, OS_SZ_BF );
BytesToRaw( idbRead, acStream, len );
iResult = g_oProtocol.f_iOnPacketCheck( acStream, len );
if( iResult != OS_OK )
return OS_ERR;

n = g_oProtocol.f_iOnDecode( acStream, acData );
acData[ n ] = 0x00;
if( strstr( acData, ID_BROADCAST ) ) // ID_BROADCAST...is an identifier string.
{
m_bUDPAck = true;
lbTabMsg->Text = L"udp CONNECT OK";
__dw( L"udp CONNECT OK" );
f_iOnNetworkUDPClose();
return OS_OK;
}

UDP_TRX:

spf( acTmp, OS_SZ_BF, "___TEST-MOBILE-%i___", m_cnt++ );
iResult = g_oProtocol.f_iOnEncode( ID_CMD_BROADCAST, acTmp, acBuf );
if( iResult <= 0 )
return OS_ERR;

idbWrite.Length = iResult;
idbWrite = RawToBytes( acBuf, iResult );

try
{
udp->SendBuffer( idbWrite );
}
catch( const EIdSocketError& e )
{
}
catch( const Exception &e )
{
}
catch( ... )
{
}

return OS_OK;
}

- To inform, sample source above works fine under TThread::Execute(), but caused exception under OnTimer().

Where f_iOnThreadProc() is called within Execute() via:

void __fastcall TXThread::Execute()
{
if( !fMain ) return;

while( !m_bStop )
{
fMain->f_iOnThreadProc();

Sleep( 1000 );
}
}

int TfMain::f_iOnThreadProc (void)
{
f_iOnNetworkUDPProc();

return OS_OK;
}

Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02