Thread View: borland.public.cppbuilder.nativeapi
11 messages
11 total messages
Started by Wiebe Vos
Tue, 11 Sep 2007 13:17
CreateProcess() in Automation server freezes caller
Author: Wiebe Vos
Date: Tue, 11 Sep 2007 13:17
Date: Tue, 11 Sep 2007 13:17
107 lines
4155 bytes
4155 bytes
Hi,
(BCB6+SP4)
I'm succesfully launching a thirdparty program via CreateProcess()
in a COM automation server. The latter is called from our main
application (which is also a COM automation server so both programs
can exchange information).
The problem I face is that, during the execution of the thirdparty program,
the
main application is completely blocked. No mouse- and keyboardactions are
possible. (Other application are not affected...).
How can I avoid this?
Thanks in advance,
Wiebe
The code launching the thirdparty program:
//---------------------------------------------------------------------------
// ret=false is Succesfull
// DoDownload ( char *path, char *command, bool wait=true )
//------------
bool FBaseDownloader::DoDownload ( char *path, char *command, bool wait )
{
bool ret=true, exit=false;
AnsiString s;
STARTUPINFO startUpInfo={sizeof(STARTUPINFO), 0};
PROCESS_INFORMATION processInfo={0};
while ( exit EQ false )
{
exit = true;
Log ( "Start Download" );
if ( FileExists ( path ) EQ false )
{
Beep();
s = (AnsiString)"FOUT: Downloader: " + path + " niet aanwezig...";
Log(s);
ShowMessage(s);
break;
}
if ( CreateProcess (
path,
command,
NULL,
NULL,
false,
CREATE_DEFAULT_ERROR_MODE,
NULL,
VendorDir,
&startUpInfo,
&processInfo ) EQ true )
{
// Disabled-------->> MsgWaitForMultipleObjects() + Sleep(0) does not cure
the problem!
// TMsg msg;
// DWORD wRet;
// int test=WAIT_OBJECT_0;
// do
// {
// Sleep(0);
// wRet = MsgWaitForMultipleObjects
// (
// 1, // 1 handle to wait on
// &processInfo.hProcess, // the handle
// false, // wake on any event
// INFINITE, // wait without timeout
// QS_PAINT | // wake on paint messages
// QS_SENDMESSAGE // or messages from other threads
// );
// if ( wRet EQ WAIT_FAILED )
// break; // can do little here
// if ( wRet EQ (WAIT_OBJECT_0 + 1) )
// {
// while ( PeekMessage( &msg, 0, WM_PAINT, WM_PAINT, PM_REMOVE ) )
// DispatchMessage ( &msg );
// }
// }
// while ( wRet NEQ WAIT_OBJECT_0 );
// ------------------------------------------------------<<
WaitForSingleObject ( processInfo.hProcess, wait
? 60*1000
: 0 );
CloseHandle( processInfo.hProcess );
CloseHandle( processInfo.hThread );
ret = false;
}
else
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
s = (AnsiString)"FOUT: Download:" + path + "\n" + (char*)lpMsgBuf;
Log(s);
Beep();
ShowMessage(s);
LocalFree( lpMsgBuf );
}
Log ( "End Download" );
}
return ret;
}
Re: CreateProcess() in Automation server freezes caller
Author: Ed Mulroy [TeamB]
Date: Tue, 11 Sep 2007 13:24
Date: Tue, 11 Sep 2007 13:24
116 lines
4747 bytes
4747 bytes
This is only a guess but you might try creating a thread in which you do the
CreateProcess. I expect the result to be Windows apportioning time slices
between threads and therefore allowing the main thread mouse and keyboard
messages to flow.
. Ed
> Wiebe Vos wrote in message
> news:46e69558$1@newsgroups.borland.com...
>
> (BCB6+SP4)
> I'm succesfully launching a thirdparty program via CreateProcess()
> in a COM automation server. The latter is called from our main
> application (which is also a COM automation server so both programs
> can exchange information).
> The problem I face is that, during the execution of the thirdparty
> program, the
> main application is completely blocked. No mouse- and keyboardactions are
> possible. (Other application are not affected...).
>
> How can I avoid this?
>
> Thanks in advance,
> Wiebe
>
> The code launching the thirdparty program:
> //---------------------------------------------------------------------------
> // ret=false is Succesfull
> // DoDownload ( char *path, char *command, bool wait=true )
> //------------
> bool FBaseDownloader::DoDownload ( char *path, char *command, bool wait )
> {
> bool ret=true, exit=false;
> AnsiString s;
> STARTUPINFO startUpInfo={sizeof(STARTUPINFO), 0};
> PROCESS_INFORMATION processInfo={0};
> while ( exit EQ false )
> {
> exit = true;
> Log ( "Start Download" );
> if ( FileExists ( path ) EQ false )
> {
> Beep();
> s = (AnsiString)"FOUT: Downloader: " + path + " niet aanwezig...";
> Log(s);
> ShowMessage(s);
> break;
> }
> if ( CreateProcess (
> path,
> command,
> NULL,
> NULL,
> false,
> CREATE_DEFAULT_ERROR_MODE,
> NULL,
> VendorDir,
> &startUpInfo,
> &processInfo ) EQ true )
> {
> // Disabled-------->> MsgWaitForMultipleObjects() + Sleep(0) does not cure
> the problem!
> // TMsg msg;
> // DWORD wRet;
> // int test=WAIT_OBJECT_0;
> // do
> // {
> // Sleep(0);
> // wRet = MsgWaitForMultipleObjects
> // (
> // 1, // 1 handle to wait on
> // &processInfo.hProcess, // the handle
> // false, // wake on any event
> // INFINITE, // wait without timeout
> // QS_PAINT | // wake on paint messages
> // QS_SENDMESSAGE // or messages from other threads
> // );
> // if ( wRet EQ WAIT_FAILED )
> // break; // can do little here
> // if ( wRet EQ (WAIT_OBJECT_0 + 1) )
> // {
> // while ( PeekMessage( &msg, 0, WM_PAINT, WM_PAINT,
> PM_REMOVE ) )
> // DispatchMessage ( &msg );
> // }
> // }
> // while ( wRet NEQ WAIT_OBJECT_0 );
> // ------------------------------------------------------<<
> WaitForSingleObject ( processInfo.hProcess, wait
> ? 60*1000
> : 0 );
> CloseHandle( processInfo.hProcess );
> CloseHandle( processInfo.hThread );
> ret = false;
> }
> else
> {
> LPVOID lpMsgBuf;
> FormatMessage(
> FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
> NULL,
> GetLastError(),
> MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), // Default language
> (LPTSTR) &lpMsgBuf,
> 0,
> NULL );
> s = (AnsiString)"FOUT: Download:" + path + "\n" + (char*)lpMsgBuf;
> Log(s);
> Beep();
> ShowMessage(s);
> LocalFree( lpMsgBuf );
> }
> Log ( "End Download" );
> }
> return ret;
> }
Re: CreateProcess() in Automation server freezes caller
Author: Wiebe Vos
Date: Tue, 11 Sep 2007 15:24
Date: Tue, 11 Sep 2007 15:24
12 lines
1481 bytes
1481 bytes
Thanks Ed, > This is only a guess but you might try creating a thread in which you do > the CreateProcess. I expect the result to be Windows apportioning time > slices between threads and therefore allowing the main thread mouse and > keyboard messages to flow. I did CreateProcess() in a thread. However this does not solve the problem. (Also not if using MsgWaitForMultipleObjects() instead of WaitForSingleObject()) Wiebe
Re: CreateProcess() in Automation server freezes caller
Author: Bob Gonder
Date: Tue, 11 Sep 2007 16:10
Date: Tue, 11 Sep 2007 16:10
45 lines
2455 bytes
2455 bytes
Wiebe Vos wrote:
>main application is completely blocked. No mouse- and keyboardactions are
>possible. (Other application are not affected...).
>
>How can I avoid this?
By processing those messages as well.
>// do
>// {
>// Sleep(0);
Sleep() is redundant.
>// wRet = MsgWaitForMultipleObjects
>// (
>// 1, // 1 handle to wait on
>// &processInfo.hProcess, // the handle
>// false, // wake on any event
>// INFINITE, // wait without timeout
>// QS_PAINT | // wake on paint messages
>// QS_SENDMESSAGE // or messages from other threads
Very much too restrictive. Use QS_ALLINPUT instead.
>// );
>// if ( wRet EQ (WAIT_OBJECT_0 + 1) )
>// {
>// while ( PeekMessage( &msg, 0, WM_PAINT, WM_PAINT, PM_REMOVE ) )
>// DispatchMessage ( &msg );
Again, too restrictive.
You say mouse and keyboard are locked, that would
be because you are only looking at paint messages.
Use general message pump.
while ( PeekMessage( &msg, 0, 0,0, PM_REMOVE ) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
};
>// }
>// }
>// while ( wRet NEQ WAIT_OBJECT_0 );
Re: CreateProcess() in Automation server freezes caller
Author: Bob Gonder
Date: Tue, 11 Sep 2007 16:55
Date: Tue, 11 Sep 2007 16:55
12 lines
1590 bytes
1590 bytes
Wiebe Vos wrote: >I did CreateProcess() in a thread. However this does not solve the problem. >(Also not if using MsgWaitForMultipleObjects() instead of >WaitForSingleObject()) PeekMessage only sees messages for the current thread. If you create a thread to run the CreateProcess() : 1) The thread won't be getting any messages. 2) Your application won't be waiting for the process (unless you are waiting for the thread, which puts you back to the same problem).
Re: CreateProcess() in Automation server freezes caller
Author: Remy Lebeau (TeamB)
Date: Tue, 11 Sep 2007 17:25
Date: Tue, 11 Sep 2007 17:25
26 lines
1922 bytes
1922 bytes
"Wiebe Vos" <wiebe@foxware.nl> wrote in message news:46e69558$1@newsgroups.borland.com... > I'm succesfully launching a thirdparty program via CreateProcess() > in a COM automation server. The latter is called from our main > application (which is also a COM automation server so both > programs can exchange information). You don't need 2 COM servers for bi-directional communication to work. > The problem I face is that, during the execution of the thirdparty > program, the main application is completely blocked. As it should be. You designed your COM function to block the caller until the work is done. > How can I avoid this? You need to either 1) change the design of your COM function to not block the caller anymore, such as by exposing an asynchronous event that is triggered when the work is done, or else 2) call the function in the context of a worker thread within the main app instead of in its main thread. Gambit
Re: CreateProcess() in Automation server freezes caller
Author: Wiebe Vos
Date: Wed, 12 Sep 2007 10:09
Date: Wed, 12 Sep 2007 10:09
23 lines
1587 bytes
1587 bytes
Hi Bob,
> Bob Gonder wrote:
> Very much too restrictive. Use QS_ALLINPUT instead.
> Again, too restrictive.
> You say mouse and keyboard are locked, that would
> be because you are only looking at paint messages.
> Use general message pump.
>
> while ( PeekMessage( &msg, 0, 0,0, PM_REMOVE ) )
> {
> TranslateMessage(&msg);
> DispatchMessage(&msg);
> }
That's it.
So CreateProcess (not in a TThread) and MsgWaitForMultipleObjects
solved this problem.
Thanks,
Wiebe
Re: CreateProcess() in Automation server freezes caller
Author: Wiebe Vos
Date: Wed, 12 Sep 2007 10:39
Date: Wed, 12 Sep 2007 10:39
29 lines
2005 bytes
2005 bytes
Hi Remy, Remy Lebeau (TeamB) wrote: > You don't need 2 COM servers for bi-directional communication to work. Agreed. However both programs also serve other purposes. > As it should be. You designed your COM function to block the caller until > the work is done. My brief explanation about the design requires more clarification: The automationserver, once initially started from the main application, runs independend in the background and at certain intervals (via a timer) it launches the thirdparty program. This downloads a substantial amount of (stockmarket) data to a file, whose content is subsequently processed by the automationserver. After completion, the automationserver notifies the main application who takes further care of the data. So the main application (though fully blocked during the execution of the thirdparty program) is not the 'caller' but the automation server (also blocked) is. Anyhow the problem is solved by applying Bob Gonders suggestion. Thanks, Wiebe
Re: CreateProcess() in Automation server freezes caller
Author: Remy Lebeau (TeamB)
Date: Wed, 12 Sep 2007 17:28
Date: Wed, 12 Sep 2007 17:28
27 lines
2409 bytes
2409 bytes
"Wiebe Vos" <wiebe@foxware.nl> wrote in message news:46e7c1df$1@newsgroups.borland.com... > The automationserver, once initially started from the main application, > runs independend in the background and at certain intervals (via a timer) > it launches the thirdparty program. This downloads a substantial amount > of (stockmarket) data to a file, whose content is subsequently processed > by the automationserver. After completion, the automationserver notifies > the main application who takes further care of the data. All the more reason you should be using asynchronous events. Then there is no blockage at all. When the work is done, the server will tell the app when it is ready. The main application does not have to wait on anything. This works especially well if the download is in its own thread that notifies the server when the download is finished. Then the download is not blocking anything, not even the server that is doing the download. > Anyhow the problem is solved by applying Bob Gonders suggestion. Technically yes, but I would not recommend running a message queue from inside the server itself. It has no way of knowing what kind of app is using it, what kind of messages to expect, whether those messages will cause reentrant issues if processed at the wrong time, etc. Gambit
Re: CreateProcess() in Automation server freezes caller
Author: Bob Gonder
Date: Thu, 13 Sep 2007 00:03
Date: Thu, 13 Sep 2007 00:03
27 lines
2273 bytes
2273 bytes
Ok, so taking Remy's suggestion (which is usually a good idea,BTW) Your Main Application (MA) spawns the automation server (AS). It should not wait for anything, just continue it's message loop. (maybe set a flag so it doesn't spawn another copy) MA is non-blocking. The AS, on a timer event spawns a thread that spawns the 3rdParty. The thread waits, but the Timer event continues after spawning the thread. Timer Event is non-blocking. AS is not blocked. Thread is blocking on 3rd party. After the download, the thread raises an event, or PostMessage to the AS that the download is complete, then exits. The AS sees the message and either processes the data (blocking) or preferably spawns another thread to process the data (non-blocking) (or the original download thread could have processed the data, also non-blocking to AS). After the data is processed, AS (or the processing thread) notifies MA (PostMessage or other IPC) and continues waiting for another timer event. Simple. MA and AS use their normal message loop, no extra checking required. Only one block, and that's in a thread that is not connected to the UI.
Re: CreateProcess() in Automation server freezes caller
Author: Wiebe Vos
Date: Thu, 13 Sep 2007 15:26
Date: Thu, 13 Sep 2007 15:26
5 lines
1126 bytes
1126 bytes
Bob and Remy, thank you very much. The points you are making needs me to reconsider a couple of things. Wiebe
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads