|
OK, that is right. The first call to WaitForSingle object will surely return WAIT_TIMEOUT. But when the bool is switched, the loop in CAnyDlg::Thread() stops. This means that the created thread will terminate sometime later. From this point on, a continous call to WaitForSingleObject should return WAIT_OBJECT_0 after some time. But that doesn't happen.
Tha fact that concerns me is that the code works if i take away the SetWindowText() in the thread or i i call PeekMessage in the WaitForSingleObject loop...this must have something to do with the message queue...
|
|
|
|
|
If this secondary thread's handle is closed while the wait is still pending, WaitForSingleObject() 's behavior is undefined.
Have you seen these two articles:
http://www.flounder.com/workerthreads.htm
http://www.flounder.com/uithreads.htm
|
|
|
|
|
One solution is a boolean variable to indicate the status of the loop.
Kuphryn
|
|
|
|
|
Aha!
m_cstaAnyStatic.SetWindowText causes a WM_SETTEXT message to be sent to the message queue. However, while in the loop in CAnyDlg::Stop, the UI thread can't process the message (this assumes that the static control and the dialog box were created by the same thread and hence share that thread's message queue).
You're effectively deadlocked.
It's typically a bad idea to directly modify any controls on the UI thread from a worker thread. It's better to define a custom message and post (not send) messages to the window to effect any changes in UI state. PostMessage just queues up the message, then returns; SendMessage blocks until the message is received by the window procedure, processed, and a response generated (either by returning from the window procedure, or by calling ReplyMessage ).
|
|
|
|
|
Good catch!! The post vs. send message problem is common, but is sometimes hidden in the problem description.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
Hi guys,
thanx for the hints! I will try the PostMessage()!
|
|
|
|
|
I execute an application in a console with ShellExecuteEx, but when this application ends I would the console's windows doesn't close because this function works like a daemon. So, how can I keep the window open?
thanks
|
|
|
|
|
chadell wrote:
...the console's windows doesn't close because this function works like a daemon. So, how can I keep the window open?
Maybe I'm reading this wrong, but first you say that the window doesn't close and then you say that you want to keep it open. Am I missing something?
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
sorry my english, david.
my problem is that the console application (executed by ShellExecuteEx) ends its execution and then closes its window, but the application needs to keep the window open until I close this(I thought to do this by the TerminateProcess with the hProcess returned by ShellExecuteEx). For more details, the application I want to run is MRTG.
thanks
|
|
|
|
|
One possible solution is to simply add a call to get() or another C++ I/O function that waits for the user to press ENTER before terminating.
Lookup ShellExecuteEx() at MSDN.
Kuphryn
|
|
|
|
|
A Visual Basic Application accessed a C++ DLL. That DLL must allocate a block of memory and populate it. It should then pass the pointer to the first elements back to VB for outputing the results.
Q: How can I free the memory from the VB once I am done? Is using functions such a GlobalFree or HeapFree the solutions? Are there any caveats, problems?
Currently I have space allocated in VB, the pointer is passed to C++, and then space deallocated in VB. The problem here is that I do not know beforehand the exact size of the array, and the "to be on the safe side" allocation is quite wasteful.
Please help.
Thank you
|
|
|
|
|
I guess the proper question here is what is Visual C++'s new operator equivalent to : GlobalAlloc, HeapAlloc, LocalAlloc, CoTaskMemAlloc, etc?
If I know that, then I can probably use the appropriate method to free memory in VB.
|
|
|
|
|
Why can't you write a function in the DLL that does the deletion?
My neighbours think I am crazy - but they don't know that I have a trampoline. All they see my head bobbing up and down over the fence every five seconds
|
|
|
|
|
Because I need to output results in VB from this array before I deallocate it.
|
|
|
|
|
JWood's suggestion still applies. You have one function in the C++ DLL that allocates the memory, and another function in that DLL that deallocates the same memory. After the memory has been allocated, but before it is deallocated, the VB code can use it.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
This is actually an interesting point. I haven't thought about doing this before. I guess the question then becomes: does calling the DLL twice create more overhead than allocating excess amount of memory in VB?
|
|
|
|
|
"Calling a DLL" is actually a misnomer. The overhead comes in loading the DLL into the address space of the process. Once that happens, a function call is a function call.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
Like the others, the new operator allocates memory, but it's the only one that, when operating on objects, calls their constructor. Trying to mix memory-management routines has no positive results.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
What if I need to allocate a pure byte array, and I can take care of reading the data using CopyMemory in the appropriate format? Would that make a difference?
I guess new operator is compiler specific, but I found no reference to what it actually does. Other functions have different twists to it: you can zero the elements, you can move memory, etc. My theory is that if one of them does exactly what new in C++ compiler does, then things should be good.
Am I mistaken?
|
|
|
|
|
Anton A. Loukine wrote:
I guess new operator is compiler specific, but I found no reference to what it actually does.
Like this?
The most important thing is to not mix "allocate" and "deallocate" routines. In other words, new cannot be used with free() , and malloc() cannot be used with delete .
Both the DLL and EXE have their own list(s) of allocated memory blocks. If the DLL allocates a block of memory, for the creation of a new instance of a class, this memory is marked in the allocation list of the DLL. If the EXE tries to free this memory, the run-time library looks through its list of allocated memory blocks and fails (usually with a GP fault). Thus, even if the memory between the DLL and the EXE is completely shared, the logic for managing allocation breaks if two modules mix their allocation schemes.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
This is clear. However, if I exit the DLL, go back to VB, and then come back to the DLL with the pointer created in the first round, will that list of allocated memory blocks still be there? Also, you said that the DLL is loaded into memory when it's called.
Let's say we have a VB function:
{
....
call DLL
.....
call same DLL
....
}
is it going to load the DLL and unload it twice or once?
Thank you very much
|
|
|
|
|
Anton A. Loukine wrote:
However, if I exit the DLL,
Not sure what you mean by "exit the DLL" as it is either implicitly or explicitly linked. DLLs remain in the address space of the process, with all of their memory blocks intact, until the process explicitly unloads the DLL or the process itself goes away.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
I actually tried to implement your suggestion, but they do not seem to work with my code:
In C++, I have:
short _stdcall QrgAlloc( double* dArray )
{
dArray = new double[ 2 ];
dArray[ 0 ] = 2.34;
dArray[ 1 ] = 2.55;
return 1;
}
short _stdcall QrgFree( double* dArray )
{
delete [] dArray;
return 1;
}
In VB, I have:
Dim l As Long
Dim d As Double
Dim nReturn As Integer
nReturn = QrgAlloc(l)
CopyMemory d, l, 4
MsgBox (d)
CopyMemory d, l + 4, 4
MsgBox (d)
nReturn = QrgFree(l)
That outputs wrong values and then crashes when freeing memory. Any thoughts?
Thanks
|
|
|
|
|
"double" is 8 bytes long in C...
"...Ability to type is not enough to become a Programmer. Unless you type in VB. But then again you have to type really fast..."
Me
|
|
|
|
|
Thanks Igor.
I picked up on that typo later on, too; however, the major issue remains: why does it crash when I supply the memory address to C++ dll for the second time for deallocation. Is the double* pointer a value of a "Long" type (4 bytes)?. If it is, then it doesn't really make sense why it's not working. Unless the memory addresses are wiped out by the time the DLL function exists.
|
|
|
|