ndmiller
asked on
OLE Automation with Threads
My main thread calls this function when a menu is clicked on..Notice the last function call it a start of a thread.
The next section of code is the thread code...
void CYAGMeasurementSystemProje ctDoc::OnB egintest()
{
// TODO: Add your command handler code here
if (!theMeasurementSession.Ge tOutputFil eName())
return;
if (!theMeasurementSession.Ve rify())
return;
FrequencySetter.Initialize (&theMeasu rementSess ion, &theJAG, &MeasurementTaker);
MeasurementTaker.Initializ e(&theJAG, &theMeasurementSession, &DataRecorder);
DataRecorder.Initialize(&t heMeasurem entSession , FrequencySetter.NumberOfFr equencyPoi nts());
MeasurementThreadHandle = AfxBeginThread(CMeasuremen tThread, nothing);
}
UINT CMeasurementThread ( LPVOID param )
{
//const COleVariant vOpt((long)DISP_E_PARAMNOT FOUND, VT_ERROR);
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT _FAILED);
return FALSE;
}
POSITION DocTemplatePosition = AfxGetApp()->GetFirstDocTe mplatePosi tion();
CSingleDocTemplate* m_pDocTemplate = (CSingleDocTemplate *) AfxGetApp()->GetNextDocTem plate(DocT emplatePos ition);
POSITION DocPosition = (*m_pDocTemplate).GetFirst DocPositio n();
CYAGMeasurementSystemProje ctDoc* Doc = (CYAGMeasurementSystemProj ectDoc *)(*m_pDocTemplate).GetNex tDoc(DocPo sition);
(*Doc).BeginMeasurements() ;
}
Here is the BeginMeasurments code that is called
void CYAGMeasurementSystemProje ctDoc::Beg inMeasurem ents()
{
FrequencySetter.BeginMeasu rements();
}
This is the same Frequency Setter Objec that is Initialized before the Thread is called. This FrequencySetter Object is a private data memeber of the CYAGMeasurementSystemProje ctDoc class. This FrequencySetter Object also has a pointer to the DataRecorder, which is also a private member of the CYAGMeasurementSystemProje ctDoc class. Notice in the new thread, the function BeginMeasurements is called. This function accesses the DataRecorder which accesses an Excel _Application object..but it will not access the object from within the new thread. All this code will work if I Initialize the DataRecorder (which contains the Excel Application) in the same thread that I access it from, but i can't do that?..
If there are any questions, please ask. thanks
The next section of code is the thread code...
void CYAGMeasurementSystemProje
{
// TODO: Add your command handler code here
if (!theMeasurementSession.Ge
return;
if (!theMeasurementSession.Ve
return;
FrequencySetter.Initialize
MeasurementTaker.Initializ
DataRecorder.Initialize(&t
MeasurementThreadHandle = AfxBeginThread(CMeasuremen
}
UINT CMeasurementThread ( LPVOID param )
{
//const COleVariant vOpt((long)DISP_E_PARAMNOT
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT
return FALSE;
}
POSITION DocTemplatePosition = AfxGetApp()->GetFirstDocTe
CSingleDocTemplate* m_pDocTemplate = (CSingleDocTemplate *) AfxGetApp()->GetNextDocTem
POSITION DocPosition = (*m_pDocTemplate).GetFirst
CYAGMeasurementSystemProje
(*Doc).BeginMeasurements()
}
Here is the BeginMeasurments code that is called
void CYAGMeasurementSystemProje
{
FrequencySetter.BeginMeasu
}
This is the same Frequency Setter Objec that is Initialized before the Thread is called. This FrequencySetter Object is a private data memeber of the CYAGMeasurementSystemProje
If there are any questions, please ask. thanks
First of all if you want COM support you have to call:
::CoInitialize (NULL);
from your thread before calling any other COM function.
In order to pass COM interface from one thread to the other you have to marshall it.
In your primary thread call:
hr = ::CoMarshalInterThreadInte rfaceInStr eam (IID, pHandler, &pStream);
It takes COM pointer and returns (last parameter) a pointer to newly create IStream interface.
You can use that IStream pointer in the other thread to get marshalled pointer:
hr = ::CoGetInterfaceAndRelease Stream (pStream, IID, (void**)&pThreadHandler);
If you need further explanation let me know.
hr = ::CoGetInterfaceAndRelease Stream (m_pRegHandler->m_pStream, IID_IMsgHandler, (void**)&(m_pRegHandler->m _pDispatch Handler));
::CoInitialize (NULL);
from your thread before calling any other COM function.
In order to pass COM interface from one thread to the other you have to marshall it.
In your primary thread call:
hr = ::CoMarshalInterThreadInte
It takes COM pointer and returns (last parameter) a pointer to newly create IStream interface.
You can use that IStream pointer in the other thread to get marshalled pointer:
hr = ::CoGetInterfaceAndRelease
If you need further explanation let me know.
hr = ::CoGetInterfaceAndRelease
ASKER
PMazur ..Please check back in 15 min or so..i will most likely have questions..i am going to try to read and understand a little before I ask..thanks
ASKER
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec t\YAGMeasu rementSyst emProject. cpp(69) : error C2065: 'hr' : undeclared identifier
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec t\YAGMeasu rementSyst emProject. cpp(69) : error C2275: 'IID' : illegal use of this type as an expression
c:\program files\microsoft visual studio\vc98\mfc\include\af xwin.h(127 0) : see declaration of 'IID'
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec t\YAGMeasu rementSyst emProject. cpp(69) : error C2065: 'pHandler' : undeclared identifier
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec t\YAGMeasu rementSyst emProject. cpp(69) : error C2065: 'pStream' : undeclared identifier
Error executing cl.exe.
These are the errors that I get...I put the first line in the InitInstance of my CYAGMeasurementSystemProje ctApp which has public Inheritance from CWinApp...I am going to see if i can read the MSDN online documentation on this function...if you care to explain more that would be cool...Namely..everything i guess..like...what is the stream object and do i have to have it as a data member to a class so that it is not destroyed out of the InitIntance scope?...
Thanks a lot for your time...
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec
c:\program files\microsoft visual studio\vc98\mfc\include\af
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec
Error executing cl.exe.
These are the errors that I get...I put the first line in the InitInstance of my CYAGMeasurementSystemProje
Thanks a lot for your time...
ASKER
Also, how do i get a pointer to my interface that I need marshalled?....Is the interface the excel9.h classes?...sorry about these stupid questions, but i feel like i am swimming around trying to grasp on to something...thanks :)
ASKER
Just to give you more information about my project...it might or might not help..
I am createing the following objects like so:
_Application ExcelApp; //Excel application object
Workbooks ExcelWorkbooks; //Excel workbooks object
_Workbook ExcelWorkbook; //Excel workbook object
Worksheets ExcelWorksheets; //Excel worksheets object
_Worksheet ExcelWorksheet; //Excel worksheet object
Range ExcelRange; //Excel range object
_Chart ExcelChart; //Excel chart object
I don't know if have to use a class derived from COleDocObjectItem or not...maybe my problem doesn't have anything to do with this but i thought you might want to know how this is working so far..
Then in the DataRecorder Initialize function which is called before the second thread spawns off..this code is called...
ExcelApp.SetVisible(true);
ExcelWorkbooks = ExcelApp.GetWorkbooks();
ExcelWorkbook = ExcelWorkbooks.Add(vOpt);
ExcelWorksheets = ExcelWorkbook.GetWorksheet s();
ExcelWorksheet = ExcelWorksheets.GetItem(CO leVariant( (short)1)) ;
Thanks again for your help..I can't really seem to find anyone here at work that knows how to do this..(i have been working on it for a week)..
I am createing the following objects like so:
_Application ExcelApp; //Excel application object
Workbooks ExcelWorkbooks; //Excel workbooks object
_Workbook ExcelWorkbook; //Excel workbook object
Worksheets ExcelWorksheets; //Excel worksheets object
_Worksheet ExcelWorksheet; //Excel worksheet object
Range ExcelRange; //Excel range object
_Chart ExcelChart; //Excel chart object
I don't know if have to use a class derived from COleDocObjectItem or not...maybe my problem doesn't have anything to do with this but i thought you might want to know how this is working so far..
Then in the DataRecorder Initialize function which is called before the second thread spawns off..this code is called...
ExcelApp.SetVisible(true);
ExcelWorkbooks = ExcelApp.GetWorkbooks();
ExcelWorkbook = ExcelWorkbooks.Add(vOpt);
ExcelWorksheets = ExcelWorkbook.GetWorksheet
ExcelWorksheet = ExcelWorksheets.GetItem(CO
Thanks again for your help..I can't really seem to find anyone here at work that knows how to do this..(i have been working on it for a week)..
ASKER
ExcelApp.CreateDispatch("E xcel.Appli cation");
if (!ExcelApp)
{
AfxMessageBox("Cannot start Excel.");
return;
}
This is the code that I am useing to create the excel Application.. I don't have anything about a COleClientItem yet..do i need that?
if (!ExcelApp)
{
AfxMessageBox("Cannot start Excel.");
return;
}
This is the code that I am useing to create the excel Application.. I don't have anything about a COleClientItem yet..do i need that?
ASKER
Adjusted points from 300 to 400
Sorry, I was offline. I will get back to you within couple minutes.
I will try to be more specific.
You use class wizard to import those classes (_Application, etc.) from typelib, don't you?
In that case your imported classes are derived from COleDisptachDriver, and original IDispatch pointer is kept in public member variable: m_lpDispatch. This pointer should be passed as a second parameter to ::CoMarshall...
When you call CreateDispatch you use ProgId of "Excel.Application". Youhave to obtain its CLSID:
IID iidExcel;
::CLSIDfromProgID ("Excel.Application", &iidExcel);
And the last thing you need to declare
IStream* pStream;
That pointer must be accessible from your both threads.
Now you can call:
HRESULT hr;
hr = ::CoMarshalInterThreadInte rfaceInStr eam (iidExcel, ExcelApp.m_lpDispatch, &pStream);
You use class wizard to import those classes (_Application, etc.) from typelib, don't you?
In that case your imported classes are derived from COleDisptachDriver, and original IDispatch pointer is kept in public member variable: m_lpDispatch. This pointer should be passed as a second parameter to ::CoMarshall...
When you call CreateDispatch you use ProgId of "Excel.Application". Youhave to obtain its CLSID:
IID iidExcel;
::CLSIDfromProgID ("Excel.Application", &iidExcel);
And the last thing you need to declare
IStream* pStream;
That pointer must be accessible from your both threads.
Now you can call:
HRESULT hr;
hr = ::CoMarshalInterThreadInte
Now about the other part of marshalling which is going to happen in a newly created thread.
I assume that pStream pointer and iidExcel are accessible in this thread.
First thing, COM initialization:
::CoInitialize (NULL);
Now ww will need two variables. lpDispatch will receive marshalled pointer to IDispatch from a stream and hr for error checking.
LPDISPATCH lpDispatch;
HRESULT hr;
To retrieve the pointer you have to call:
hr = ::CoGetInterfaceAndRelease Stream (pStream, iidExcel, (void**)lpDispatch);
if ( hr != S_OK )
; // ERROR
The last step. Declare variable of _Application type and attach the IDispatch pointer.
_Application appMarshalled (lpDispatch);
I hope that now it is clear. Let me know if you have encounter any problems.
I assume that pStream pointer and iidExcel are accessible in this thread.
First thing, COM initialization:
::CoInitialize (NULL);
Now ww will need two variables. lpDispatch will receive marshalled pointer to IDispatch from a stream and hr for error checking.
LPDISPATCH lpDispatch;
HRESULT hr;
To retrieve the pointer you have to call:
hr = ::CoGetInterfaceAndRelease
if ( hr != S_OK )
; // ERROR
The last step. Declare variable of _Application type and attach the IDispatch pointer.
_Application appMarshalled (lpDispatch);
I hope that now it is clear. Let me know if you have encounter any problems.
ASKER
PMazur, that helps a lot. Thanks. I have just a few more questions. I hope that you will check this :). I also did a lot of reading over the weekend so I understood a little more of what you are talking about. My question is this: When you say that I need to have my IStream object and my IDD object accessable to both threads, how do i go about making that happen. Thanks for the follow up. It looks like i might get this working after all.
ASKER
Another question, would it be possible to have a _Application object that is able to write from two threads? In other words, above you declared an appMarshalled object with a lpDispatch that was Marshalled to write. Would it be possible to have a _Application object create in another thread and marshall it?
Also is there something that i have to do in order to undo this process?
Also is there something that i have to do in order to undo this process?
ASKER
Another question, sorry about this. :)
So each excel object is derived from the COleDispatchDriver class. And each COleDispatchDriver derived object has a m_lpDispatch pointer that points to the IDispatch Interface. Lets say that I just want to write to the a _WorkSheet object, does that mean that I have to Marshall the _Application though the _Worksheet object or just the _Worksheet object?
Thanks
So each excel object is derived from the COleDispatchDriver class. And each COleDispatchDriver derived object has a m_lpDispatch pointer that points to the IDispatch Interface. Lets say that I just want to write to the a _WorkSheet object, does that mean that I have to Marshall the _Application though the _Worksheet object or just the _Worksheet object?
Thanks
>>When you say that I need to have my IStream object and my IDD object
>>accessable to both threads, how do i go about making that happen.
Plenty of possibilities:
1. global variables (very bad)
2. Declaring a struct
struct ThreadParams
{
IStream* pStream;
IID iidExcel;
};
Create an instance on a heap:
ThreadParams* pThreadParams = new ThreadParams;
Initialize it and pass that pointer to AfxBeginThread as a second argument.
You will receive that pointer as an argument in your thread function:
ThreadParams* pParams = (ThreadParams*)param;
>>accessable to both threads, how do i go about making that happen.
Plenty of possibilities:
1. global variables (very bad)
2. Declaring a struct
struct ThreadParams
{
IStream* pStream;
IID iidExcel;
};
Create an instance on a heap:
ThreadParams* pThreadParams = new ThreadParams;
Initialize it and pass that pointer to AfxBeginThread as a second argument.
You will receive that pointer as an argument in your thread function:
ThreadParams* pParams = (ThreadParams*)param;
When you done you have to delete that pointer:
delete pParams;
3. You can declare those variables as members in one of the classes used in both threads, say CYAGMeasurementSystemProje ctDoc or FrequencySetter.
delete pParams;
3. You can declare those variables as members in one of the classes used in both threads, say CYAGMeasurementSystemProje
In fact after marshalling you can access the object from both threads.
It means that you can call _Application using your original pointer from main thread. And also from your worker thread using appMarshaled.
It means that you can call _Application using your original pointer from main thread. And also from your worker thread using appMarshaled.
ASKER
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec t\CDataRec order.cpp( 132) : error C2039: 'CLSIDfromProgID' : is not a member of '`global namespace''
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec t\CDataRec order.cpp( 132) : error C2065: 'CLSIDfromProgID' : undeclared identifier
I am getting these errors with the CLSIDfromProgID function.I have tried including Ole.dll as a resource and #include "objbase.h" any ideas that might help?
C:\NDM\JAG project\Archive\Step 8 YAGMeasurementSystemProjec
I am getting these errors with the CLSIDfromProgID function.I have tried including Ole.dll as a resource and #include "objbase.h" any ideas that might help?
>>So each excel object is derived from the COleDispatchDriver class.
COleDispatchDriver is MFC-specific. It is the way MFC simplifies creating and accessing IDispatch interface.
>> And each COleDispatchDriver derived object has a m_lpDispatch pointer that points to the IDispatch Interface.
Yes.
>> Lets say that I just want to write to the a _WorkSheet object, does that mean that
>>I have to Marshall the _Application though the _Worksheet
>>object or just the _Worksheet object?
You have the choice.
1. Get the _Worksheet pointer in main thread and marshall it to the worker thread.
2. Marshall _Application pointer and get _Worksheet pointer in the worker thread.
Whatever you prefer.
COleDispatchDriver is MFC-specific. It is the way MFC simplifies creating and accessing IDispatch interface.
>> And each COleDispatchDriver derived object has a m_lpDispatch pointer that points to the IDispatch Interface.
Yes.
>> Lets say that I just want to write to the a _WorkSheet object, does that mean that
>>I have to Marshall the _Application though the _Worksheet
>>object or just the _Worksheet object?
You have the choice.
1. Get the _Worksheet pointer in main thread and marshall it to the worker thread.
2. Marshall _Application pointer and get _Worksheet pointer in the worker thread.
Whatever you prefer.
ASKER
Ok I got the error fixed..i am trying the solution right now. The function should be
CLSIDFromProgID not
CLSIDfromProgID :)
CLSIDFromProgID not
CLSIDfromProgID :)
Should be CLSIDFomProgID.
Oops, I made a mistake again.
ASKER
The lines of code
ExcelWorksheet = ExcelWorksheets.GetItem(CO leVariant( (short)1)) ;
HRESULT hr = ::CLSIDFromProgID
//this returns hr = 0 so i think it works
hr = ::CoMarshalInterThreadInte rfaceInStr eam (iidExcel, ExcelWorksheet.m_lpDispatc h, &pStream);
//this returns hr = -2147467262 so i think that i might not be working
any ideas?
ExcelWorksheet = ExcelWorksheets.GetItem(CO
HRESULT hr = ::CLSIDFromProgID
//this returns hr = 0 so i think it works
hr = ::CoMarshalInterThreadInte
//this returns hr = -2147467262 so i think that i might not be working
any ideas?
ASKER
The pStream object is declared like IStream* pStream;
ASKER
Thanks for sticking this out...This is going to be sooo great if this works..I have been trying to get this for the past week...Thank you very much
Sorry, I think I was wrong. You have to marshall _Application.
By the way, you can get a description of an error by using Error Lookup from menu Tools of VC. However, sometimes it doesn't tell anything interesting.
By the way, you can get a description of an error by using Error Lookup from menu Tools of VC. However, sometimes it doesn't tell anything interesting.
ASKER
No such interface supported
that was the error message that I got from the big neagtive value returned by the hr = ::CoMarshalInterThreadInte rfaceInStr eam (iidExcel, ExcelApp.m_lpDispatch, &pStream); line of code....
that was the error message that I got from the big neagtive value returned by the hr = ::CoMarshalInterThreadInte
Try this:
hr = ::CoMarshalInterThreadInte rfaceInStr eam (IID_IDispatch, ExcelApp.m_lpDispatch, &pStream);
And you don't need to call CLSIDFromProgID.
IID_IDispatch should be already included in your project by other headers, but just in case it is declared in oaidl.h.
And one more thing. Probably you can marshall also Worksheet (passing IID_IDispatch as a first argument to ::CoMarshall...).
Sorry for all that mess. I usually don't use COleDispatchDriver. I prefer #import directive instead. It is more flexible.
hr = ::CoMarshalInterThreadInte
And you don't need to call CLSIDFromProgID.
IID_IDispatch should be already included in your project by other headers, but just in case it is declared in oaidl.h.
And one more thing. Probably you can marshall also Worksheet (passing IID_IDispatch as a first argument to ::CoMarshall...).
Sorry for all that mess. I usually don't use COleDispatchDriver. I prefer #import directive instead. It is more flexible.
ASKER
That worked..now :)..this
When does the _Worksheet object have the ability to cross threads?
Does this call..
HRESULT hr = ::CoMarshalInterThreadInte rfaceInStr eam (IID_IDispatch, ExcelWorksheet.m_lpDispatc h, &pStream);
...make the ExcelWorksheet be able to be used across threads?
OR do i have to use the call..
hr = ::CoGetInterfaceAndRelease Stream (pStream, IID, (void**)&pThreadHandler);
and create a new _Worksheet object with the Marshalled Interface in the new thread?
When does the _Worksheet object have the ability to cross threads?
Does this call..
HRESULT hr = ::CoMarshalInterThreadInte
...make the ExcelWorksheet be able to be used across threads?
OR do i have to use the call..
hr = ::CoGetInterfaceAndRelease
and create a new _Worksheet object with the Marshalled Interface in the new thread?
ASKER
I guess i am trying to figure out what is Marshalled.
With the first call..do i marshall the interface of the ExcelWorksheet object so that it can be used across threads...or do i marshall a new Interface pointer that i have to load into a new _Worksheet object?
With the first call..do i marshall the interface of the ExcelWorksheet object so that it can be used across threads...or do i marshall a new Interface pointer that i have to load into a new _Worksheet object?
In fact, every interface is able to cross threads. The problem in our first attempts was that we passed wrong interface id.
You can use both approaches I described earlier.
You can use both approaches I described earlier.
ASKER
Humm...now i don't get it again :)
hehe..here is the line that is being used..
HRESULT hr = ::CoMarshalInterThreadInte rfaceInStr eam (IID_IDispatch, ExcelWorksheet.m_lpDispatc h, &pStream);
It returns a 0 in hr so i think that it is "working"..however...what do you mean when you say that every interface in able to cross threads?...I thought the purpose of this was to make interfaces able to cross threads..i didn't think that they could without Marshalling them?..
It seems to me that we are marshalling the interfaces not the threads..is that right?
hehe..here is the line that is being used..
HRESULT hr = ::CoMarshalInterThreadInte
It returns a 0 in hr so i think that it is "working"..however...what do you mean when you say that every interface in able to cross threads?...I thought the purpose of this was to make interfaces able to cross threads..i didn't think that they could without Marshalling them?..
It seems to me that we are marshalling the interfaces not the threads..is that right?
ASKER
hr = ::CoGetInterfaceAndRelease Stream(pSt ream, IID_IDispatch, (void**)lpDispatch);
This line returns an error...just in case you see something wrong with it :)
This line returns an error...just in case you see something wrong with it :)
ASKER
Please don't give up on this...it almost works
ASKER
Here are the calls that I am useing but I get a OLEAUT32.dll exception access error.
ExcelApp.CreateDispatch("E xcel.Appli cation");
if (!ExcelApp)
{
AfxMessageBox("Cannot start Excel.");
return;
}
ExcelApp.SetVisible(true);
HRESULT hr = ::CoMarshalInterThreadInte rfaceInStr eam (IID_IDispatch, ExcelApp.m_lpDispatch, &pStream);
Then in the other thread...
LPDISPATCH* lpDispatch;
HRESULT hr;
hr = ::CoGetInterfaceAndRelease Stream(pSt ream, IID_IDispatch, (void**)&lpDispatch);
_Application NEWApp((*lpDispatch));
NEWApp.SetVisible(0);
All the results from the Marshalling functions return 0 for ok
Any ideas?
The hr returns a 0 but the SetVisible call does this
ExcelApp.CreateDispatch("E
if (!ExcelApp)
{
AfxMessageBox("Cannot start Excel.");
return;
}
ExcelApp.SetVisible(true);
HRESULT hr = ::CoMarshalInterThreadInte
Then in the other thread...
LPDISPATCH* lpDispatch;
HRESULT hr;
hr = ::CoGetInterfaceAndRelease
_Application NEWApp((*lpDispatch));
NEWApp.SetVisible(0);
All the results from the Marshalling functions return 0 for ok
Any ideas?
The hr returns a 0 but the SetVisible call does this
I am back from lunch. I need a minute.
ASKER
No problem..I'm so glad your back :)
It seems to be working but not quite..i pasted some code for you..please ask questions...
It seems to be working but not quite..i pasted some code for you..please ask questions...
Declare lpDispatch as LPDISPATCH:
LPDISPATCH lpDispatch;
And then use it without dereferencing:
_Application NEWApp(lpDispatch);
LPDISPATCH lpDispatch;
And then use it without dereferencing:
_Application NEWApp(lpDispatch);
>>It returns a 0 in hr so i think that it is "working"..however...
>>what do you mean when you say that every interface in able
>> to cross threads?...I thought the purpose of this was to make interfaces able to
>> cross threads..i didn't think that they could without Marshalling them?..
>>It seems to me that we are marshalling the interfaces not the
>> threads..is that right?
It is like travelling on bus or train.
Everyone is able to travel, but must enter the bus before travelling and leave it at the end of trip.
>>what do you mean when you say that every interface in able
>> to cross threads?...I thought the purpose of this was to make interfaces able to
>> cross threads..i didn't think that they could without Marshalling them?..
>>It seems to me that we are marshalling the interfaces not the
>> threads..is that right?
It is like travelling on bus or train.
Everyone is able to travel, but must enter the bus before travelling and leave it at the end of trip.
ASKER
Unhandled exception in program.exe (OLEAUT32.DLL): 0xC0000005: Access Violation
That is the error that i am getting....
It is the same error that i got when I just had my last line to be ExcelApp.SetVisible(false) ; from the other thread without Marshalling the interface...
That is the error that i am getting....
It is the same error that i got when I just had my last line to be ExcelApp.SetVisible(false)
ASKER
YAH.YAYAYAYAYAYAHHHAYAYHH. .that did it....
Just a min..lemme see if the rest of the program works...
Why couldn't i declare a pointer and dereference it??
Just a min..lemme see if the rest of the program works...
Why couldn't i declare a pointer and dereference it??
ASKER
Can I take this new LPDISPATCH object and attach it to my old Application object? Therefore I would just have a new _Appllication object that could write from either thread....would that work...or would the _Application object only then be able to write from the new thread and not the old one?
Try following code:
LPDISPATCH lpDispatch;
HRESULT hr;
hr = ::CoGetInterfaceAndRelease Stream(pSt ream, IID_IDispatch, (void**)&lpDispatch);
_Application NEWApp(lpDispatch);
TRY
{
NEWApp.SetVisible(0);
}
CATCH (COleDispatchException, e)
{
e->ReportError ();
}
AND_CATCH (COleException, e)
{
e->ReportError ();
}
END_CATCH
In case that OLE exception was thrown it will display a message.
LPDISPATCH lpDispatch;
HRESULT hr;
hr = ::CoGetInterfaceAndRelease
_Application NEWApp(lpDispatch);
TRY
{
NEWApp.SetVisible(0);
}
CATCH (COleDispatchException, e)
{
e->ReportError ();
}
AND_CATCH (COleException, e)
{
e->ReportError ();
}
END_CATCH
In case that OLE exception was thrown it will display a message.
>>Can I take this new LPDISPATCH object and attach it to my old Application object?
Yes, you can.
>> Therefore I would just have a new _Appllication object that could write
>>from either thread....would that work...
No.
>>or would the _Application object only then be able to write from the new
>>thread and not the old one?
Yes.
Yes, you can.
>> Therefore I would just have a new _Appllication object that could write
>>from either thread....would that work...
No.
>>or would the _Application object only then be able to write from the new
>>thread and not the old one?
Yes.
>>Why couldn't i declare a pointer and dereference it??
You can. But, in this case you will not get what you expect since LPDISPATCH is already declared as a pointer to IDispatch, hence LPDISPATCH* is like IDispatch**.
You can. But, in this case you will not get what you expect since LPDISPATCH is already declared as a pointer to IDispatch, hence LPDISPATCH* is like IDispatch**.
ASKER
Is there a way to make a _Application object that would write from either thread?
No, as far as I know not.
ASKER
Thanks for the help....
I have one more question...if you have time...
Right now the Excel Application is in its own window...is it possible to make the view come up in my window..and if so are there many complications..i just want the _Worksheet object to be in my view and its embeded chart object...is that very hard to do?
I have one more question...if you have time...
Right now the Excel Application is in its own window...is it possible to make the view come up in my window..and if so are there many complications..i just want the _Worksheet object to be in my view and its embeded chart object...is that very hard to do?
It is completely different.
In order to embed an Excel chart you have to create your application as an OLE container.
You may want to read a little bit about it from MSDN:
http://msdn.microsoft.com/library/default.asp?URL=/library/devprods/vs6/visualc/vccore/_core_containers.htm
You will also find there a link to a tutorial teaching about OLE containers.
In order to embed an Excel chart you have to create your application as an OLE container.
You may want to read a little bit about it from MSDN:
http://msdn.microsoft.com/library/default.asp?URL=/library/devprods/vs6/visualc/vccore/_core_containers.htm
You will also find there a link to a tutorial teaching about OLE containers.
ASKER
if I have a HANDLE to a thread, how can i tell if that thread is complete?
You can call GetExitCodeThread. If the specified thread has not terminated the return status is STILL_ACTIVE.
DWORD dwExitCode;
if ( !GetExitCodeThread (hYourThread, &dwExitCode) )
{
// ERROR: use GetLastError to get specific error code.
}
if ( dwExitCode == STILL_ALIVE )
{
// Thread is still working.
}
You can also call WaitForSingleObject.
That function can wait for a specified time for the thread to finish or simply check if the thread is still working if you pass a timeout =0.
if ( WaitForSingleObject (hYourThread, 0) == WAIT_OBJECT_0 )
{
// Thread has finished.
}
DWORD dwExitCode;
if ( !GetExitCodeThread (hYourThread, &dwExitCode) )
{
// ERROR: use GetLastError to get specific error code.
}
if ( dwExitCode == STILL_ALIVE )
{
// Thread is still working.
}
You can also call WaitForSingleObject.
That function can wait for a specified time for the thread to finish or simply check if the thread is still working if you pass a timeout =0.
if ( WaitForSingleObject (hYourThread, 0) == WAIT_OBJECT_0 )
{
// Thread has finished.
}
ASKER
For the SuspendThread function
does it only pause between controling function calls or does it also pause the child function calls?..I hope that makes sense
does it only pause between controling function calls or does it also pause the child function calls?..I hope that makes sense
I am not sure if I know what you mean, but SuspendThread should be able to suspend your thread when in application code. That says documentation. Although it doesn't explain precisely what it means, my understanding is that you can suspent the thread inside a system function.
Another guess: if you issue a call to SuspendThread when a tread is inside system function the thread will be suspended after return from that function.
Is that what you wanted to know?
Another guess: if you issue a call to SuspendThread when a tread is inside system function the thread will be suspended after return from that function.
Is that what you wanted to know?
ASKER
You don't have to answer any of these questions...so just let me know when you want to stop :) and get your points...If I use PostThreadMessage i just read that I can not send it a message because ...
Messages sent by PostThreadMessage are not associated with a window. Messages that are not associated with a window cannot be dispatched by the DispatchMessage function. Therefore, if the recipient thread is in a modal loop (as used by MessageBox or DialogBox), the messages will be lost. To intercept thread messages while in a modal loop, use a thread-specific hook.
.....
However, if i use AfxBeginThread....how do I make it so that the thread will process my message that i send to it...
I want the thread to pause when i tell it but the SuspendThread doesn't work..i think it is because the controlling function look something like this
UINT ThreadFunction (LPVOID Param)
{
..
..
..
object.function
..
..
..
}
and there is a big loop in the function..so i am going to have a message passed in to do a WaitForSingleObject in the message handler...would that work?
Messages sent by PostThreadMessage are not associated with a window. Messages that are not associated with a window cannot be dispatched by the DispatchMessage function. Therefore, if the recipient thread is in a modal loop (as used by MessageBox or DialogBox), the messages will be lost. To intercept thread messages while in a modal loop, use a thread-specific hook.
.....
However, if i use AfxBeginThread....how do I make it so that the thread will process my message that i send to it...
I want the thread to pause when i tell it but the SuspendThread doesn't work..i think it is because the controlling function look something like this
UINT ThreadFunction (LPVOID Param)
{
..
..
..
object.function
..
..
..
}
and there is a big loop in the function..so i am going to have a message passed in to do a WaitForSingleObject in the message handler...would that work?
ASKER
Yea..i tried the SuspendThread..but i think that it only will work after it returns from a function call...
I took the fragment below from documentation.
The function fails if the specified thread does not have a message queue. The system creates a thread's message queue when the thread makes its first call to one of the Win32 User or GDI functions.
It looks like a message queue is create "on demand". I suggest you to call PeekMessage right after you start your thread.
And then somewhere in your thread function you have to periodically call PeekMessage to retrieve posted messages.
You can also use events to comunicate with your thread.
The function fails if the specified thread does not have a message queue. The system creates a thread's message queue when the thread makes its first call to one of the Win32 User or GDI functions.
It looks like a message queue is create "on demand". I suggest you to call PeekMessage right after you start your thread.
And then somewhere in your thread function you have to periodically call PeekMessage to retrieve posted messages.
You can also use events to comunicate with your thread.
ASKER
that sucks..the reason that i went away from the peekMessage is so that my program would respond quicker.....
if you find a way to make the AfxBeginThread command to take its Message Queue from somewhere please let me know
Thanks
if you find a way to make the AfxBeginThread command to take its Message Queue from somewhere please let me know
Thanks
ASKER
Could i just create a object that has public inheritance from a CWinThread object?
class myThread: public CWinThread
myThread CMeasurementThread;
AxfBeginThread(CMeasuremen tThread);
class myThread: public CWinThread
myThread CMeasurementThread;
AxfBeginThread(CMeasuremen
Is it so big delay when you call PeekMessage?
If you don't want messages you can use events.
If the event is reset the function WaitForSingleObject till it is set or timeout expires.
You can set and reset event from your main thread to stop and start your worker thread.
If you don't want messages you can use events.
If the event is reset the function WaitForSingleObject till it is set or timeout expires.
You can set and reset event from your main thread to stop and start your worker thread.
you can derive your thread from CWinThread, but it installs message loop and dispatches messages.
It is rather designed for showing some kinfd of UI and respond to the event that come from the user.
And if your thread is working all the time and you never returns control to CWinThread then messages are never dispatched.
It is rather designed for showing some kinfd of UI and respond to the event that come from the user.
And if your thread is working all the time and you never returns control to CWinThread then messages are never dispatched.
ASKER
ok..I guess that will work..the worker thread that i am running it search feed-back loop from a system...and it has a few nested loops...but i guess that i could a WaitForSingleObject in the loops....and the main thread could set and reset the flag...
One thing that i wanted to do was to have a abort....i wanted the nested loops to finish upon an event..is that a possiblity?
One thing that i wanted to do was to have a abort....i wanted the nested loops to finish upon an event..is that a possiblity?
So you need two event. One for pause/start and the other to terminate.
You can use WaitForMultipleObjects to wait for two handles, and take the action for each of them.
You can use WaitForMultipleObjects to wait for two handles, and take the action for each of them.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Answer accepted
ASKER
PMazur..I need to take action when the child thread is complete..however..I don't know how to do that...i tried the sample code that you gave me..here is what i am useing
int ExitCode = 0;
SetEvent(HandleArray[0]);
SetDlgItemText(IDC_STATIC, "Please wait while system shuts down");
GetExitCodeThread(AfxGetTh read(), (unsigned long *)&ExitCode);
//while (WaitForSingleObject (MeasurementThread, 0) != WAIT_OBJECT_0)
while (ExitCode == STILL_ACTIVE)
{
GetExitCodeThread(Measurem entThread, (unsigned long *)&ExitCode);
}
The problem is that GetExitCodeThread does not update ExitCode varible...
MeasurementThread is the return value from AfxBeginThread...
int ExitCode = 0;
SetEvent(HandleArray[0]);
SetDlgItemText(IDC_STATIC,
GetExitCodeThread(AfxGetTh
//while (WaitForSingleObject (MeasurementThread, 0) != WAIT_OBJECT_0)
while (ExitCode == STILL_ACTIVE)
{
GetExitCodeThread(Measurem
}
The problem is that GetExitCodeThread does not update ExitCode varible...
MeasurementThread is the return value from AfxBeginThread...
Couple things:
All those thread functions require thread handle. AfxGetThread, however, returns pointer to CWinThread.
When you create a new thread you receive also the pointer to MFC'c CWinThread:
MeasurementThreadHandle = AfxBeginThread(CMeasuremen tThread, nothing);
If you call GetExitCodeThread in a loop utilization of processor can go high.
You may want to rewrite your code as follows:
SetDlgItemText(IDC_STATIC, "Please wait while system shuts down");
while ( WaitForSingleObject (MeasurementThread->m_hThr ead, 5000) != WAIT_OBJECT_0)
{
// five seconds elapsed, and the thread is still alive
// Some feedback to user?
}
All those thread functions require thread handle. AfxGetThread, however, returns pointer to CWinThread.
When you create a new thread you receive also the pointer to MFC'c CWinThread:
MeasurementThreadHandle = AfxBeginThread(CMeasuremen
If you call GetExitCodeThread in a loop utilization of processor can go high.
You may want to rewrite your code as follows:
SetDlgItemText(IDC_STATIC,
while ( WaitForSingleObject (MeasurementThread->m_hThr
{
// five seconds elapsed, and the thread is still alive
// Some feedback to user?
}
ASKER
PMazur,
while ( WaitForSingleObject (MeasurementThread->m_hThr ead, 5000) != WAIT_OBJECT_0)
{
// five seconds elapsed, and the thread is still alive
// Some feedback to user?
}
In the feed back from user, I want to check a dialog box and see it something has been clicked and if so, I want to take the correct action. here is what i think it should/would look like in psudeo code...
MeasurementThreadHandle = AfxBeginThread(CMeasuremen tThread, HandleArray)->m_hThread;
CControlDialog dlg(HandleArray, MeasurementThreadHandle);
dlg.Create(IDD_CONTROL, this);
dlg.ShowWindow(SW_SHOW);
while (WaitForSingleObject(Measu rementThre adHandle, 0))
{
while (PeekMessage(&msg, NULL, 0, 0, 0))
{
GetMessage(&msg, 0, 0,0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//This is to process any clicks in the Dialog box
}
dlg.KillTheBoxSomeHow();
does that make sense?
while ( WaitForSingleObject (MeasurementThread->m_hThr
{
// five seconds elapsed, and the thread is still alive
// Some feedback to user?
}
In the feed back from user, I want to check a dialog box and see it something has been clicked and if so, I want to take the correct action. here is what i think it should/would look like in psudeo code...
MeasurementThreadHandle = AfxBeginThread(CMeasuremen
CControlDialog dlg(HandleArray, MeasurementThreadHandle);
dlg.Create(IDD_CONTROL, this);
dlg.ShowWindow(SW_SHOW);
while (WaitForSingleObject(Measu
{
while (PeekMessage(&msg, NULL, 0, 0, 0))
{
GetMessage(&msg, 0, 0,0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//This is to process any clicks in the Dialog box
}
dlg.KillTheBoxSomeHow();
does that make sense?
Yes, it does.
You can use dlg.DestroyWindow to kill dlgbox.
You can use dlg.DestroyWindow to kill dlgbox.
ASKER
MeasurementThreadHandle = AfxBeginThread(CMeasuremen tThread, HandleArray)->m_hThread;
CControlDialog dlg(HandleArray, MeasurementThreadHandle);
dlg->Create(IDD_CONTROL, this);
dlg.ShowWindow(SW_SHOW);
while (WaitForSingleObject(Measu rementThre adHandle, INFINITE))
{
while (PeekMessage(&msg, NULL, 0, 0, 0))
{
GetMessage(&msg, 0, 0,0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
dlg.EndDialog(0);
This is what I am trying
and this is the error that I am getting
C:\NDM\JAG project\Archive\Step 10 YAGMeasurementSystemProjec t\YAGMeasu rementSyst emProjectD oc.cpp(162 ) : error C2819: type 'CControlDialog' does not have an overloaded member 'operator ->'
c:\ndm\jag project\archive\step 10 yagmeasurementsystemprojec t\ccontrol dialog.h(1 3) : see declaration of 'CControlDialog'
C:\NDM\JAG project\Archive\Step 10 YAGMeasurementSystemProjec t\YAGMeasu rementSyst emProjectD oc.cpp(162 ) : error C2227: left of '->Create' must point to class/struct/union
If you have any idea or thoughts..that woudl be great
thanks :)
CControlDialog dlg(HandleArray, MeasurementThreadHandle);
dlg->Create(IDD_CONTROL, this);
dlg.ShowWindow(SW_SHOW);
while (WaitForSingleObject(Measu
{
while (PeekMessage(&msg, NULL, 0, 0, 0))
{
GetMessage(&msg, 0, 0,0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
dlg.EndDialog(0);
This is what I am trying
and this is the error that I am getting
C:\NDM\JAG project\Archive\Step 10 YAGMeasurementSystemProjec
c:\ndm\jag project\archive\step 10 yagmeasurementsystemprojec
C:\NDM\JAG project\Archive\Step 10 YAGMeasurementSystemProjec
If you have any idea or thoughts..that woudl be great
thanks :)
Change:
>> dlg->Create(IDD_CONTROL, this);
to
dlg.Create(IDD_CONTROL, this);
Use DestroyWindow instead of EndDialog. The latter is designed to destroy modal dialogs.
>> dlg->Create(IDD_CONTROL, this);
to
dlg.Create(IDD_CONTROL, this);
Use DestroyWindow instead of EndDialog. The latter is designed to destroy modal dialogs.
ASKER
MeasurementThreadHandle = AfxBeginThread(CMeasuremen tThread, HandleArray)->m_hThread;
CControlDialog dlg(HandleArray, MeasurementThreadHandle);
int check = dlg.Create(IDD_CONTROL, NULL);
check = dlg.ShowWindow(SW_SHOW);
while (WaitForSingleObject(Measu rementThre adHandle, 0) == WAIT_OBJECT_0)
{
while (PeekMessage(&msg, NULL, 0, 0, 0))
{
GetMessage(&msg, 0, 0,0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
dlg.EndDialog(0);
This is the new code that i am useing ..
there are no errer upon compile but the
check = dlg.ShowWindow(SW_SHOW);
returns 0 and doesn't work
CControlDialog dlg(HandleArray, MeasurementThreadHandle);
int check = dlg.Create(IDD_CONTROL, NULL);
check = dlg.ShowWindow(SW_SHOW);
while (WaitForSingleObject(Measu
{
while (PeekMessage(&msg, NULL, 0, 0, 0))
{
GetMessage(&msg, 0, 0,0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
dlg.EndDialog(0);
This is the new code that i am useing ..
there are no errer upon compile but the
check = dlg.ShowWindow(SW_SHOW);
returns 0 and doesn't work
ASKER
C:\NDM\JAG project\Archive\Step 10 YAGMeasurementSystemProjec t\YAGMeasu rementSyst emProjectD oc.cpp(160 ) : error C2664: 'int __thiscall CDialog::Create(const char *,class CWnd *)' : cannot convert parameter 1 from 'const int' to 'const char *'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
This is the error that i get when i change NULL to this
int check = dlg.Create(IDD_CONTROL, this);
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
This is the error that i get when i change NULL to this
int check = dlg.Create(IDD_CONTROL, this);
Post the declaration of CControlDialog.
ASKER
class CControlDialog : public CDialog
{
// Construction
public:
CControlDialog(HANDLE init_HandleArray[3], HANDLE init_MeasurementThread, CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CControlDialo g)
enum { IDD = IDD_CONTROL };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CControlDi alog)
protected:
virtual void DoDataExchange(CDataExchan ge* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CControlDialog )
afx_msg void OnPauseResume();
afx_msg void OnAbort();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
HANDLE HandleArray[2];
HANDLE MeasurementThread;
};
{
// Construction
public:
CControlDialog(HANDLE init_HandleArray[3], HANDLE init_MeasurementThread, CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CControlDialo
enum { IDD = IDD_CONTROL };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CControlDi
protected:
virtual void DoDataExchange(CDataExchan
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CControlDialog
afx_msg void OnPauseResume();
afx_msg void OnAbort();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
HANDLE HandleArray[2];
HANDLE MeasurementThread;
};
I don't know why compiler picks up wrong Create method.
You can try following:
int check = dlg.Create((UINT)IDD_CONTR OL, this);
Yu said that nothing happens after calling ShowWindow. In fact, when you set WS_VISIBLE style in dialog editor, the window should be automatically shown during creation.
What is this pointing to in call to dlg.Create?
You can try following:
int check = dlg.Create((UINT)IDD_CONTR
Yu said that nothing happens after calling ShowWindow. In fact, when you set WS_VISIBLE style in dialog editor, the window should be automatically shown during creation.
What is this pointing to in call to dlg.Create?
ASKER
What is this pointing to in call to dlg.Create?
What do you mean by this?....
Do you mean what is IID_CONTROL?
What do you mean by this?....
Do you mean what is IID_CONTROL?
ASKER
I think that it is calling the wrong function because "this" is of type
class CYAGMeasurementSystemProje ctDoc : public COleDocument.
and Create wants Wind*
could that be?
class CYAGMeasurementSystemProje
and Create wants Wind*
could that be?
Yap. You have to pass a pointer to a window which will be a parent for your dialog. You can use AfxGetMainWnd to get app window.
ASKER
BOOL check = dlg.Create((UINT)IDD_CONTR OL, AfxGetMainWnd());
Now the window pops up for a small amount of time and then goes away...
and it is in the upper left part of the screen...
Now the window pops up for a small amount of time and then goes away...
and it is in the upper left part of the screen...
ASKER
Ok i made it centered with the centered check mark in the dialog editor under properties....
but it still just flashs up and then disapears...any ideas why?
but it still just flashs up and then disapears...any ideas why?
ASKER
it is like the thing is being painted over or something..i just don't get it
Do you see dialog when you set the breakpoint after dlg.Create returned?
ASKER
yea..the dialog will pop up and then go away
But if you are stopped in a debugger does it remain?
In other words, I want to know if the dialog box stays visible after Create mathod finishes. If not that the problem is in creation. If it stays then your thread is very fast.
In other words, I want to know if the dialog box stays visible after Create mathod finishes. If not that the problem is in creation. If it stays then your thread is very fast.
ASKER
The dialog box will not stay there for a long time....as soon as the screen is redrawn it will dissappear...
if i set a break point right after the create line..i see a gray box where it should be...but the whole screen not quite drawn properly..but then when I go past the break point....it will go away..
if i set a break point right after the create line..i see a gray box where it should be...but the whole screen not quite drawn properly..but then when I go past the break point....it will go away..
ASKER
i don't think that it stays visible after the create method finishes...
because I put a break point on the destroy line and I don't even get to it..so i don't see where the dialog box would be getting destroyed from my line
because I put a break point on the destroy line and I don't even get to it..so i don't see where the dialog box would be getting destroyed from my line
Let me do small experiment and I will get back to you within couple minutes.
Do you have any visible window in you application?
ASKER
What do you mean be visible window...I have the window that MFC exe wizard creates for me....
so "yes"..maybe :)..
so "yes"..maybe :)..
What kind of application did you create (SDI, MDI or Dialog)?
If dialog is CControlDialog your main window?
Did you select any styles in dialog editor?
It is very weird that your dialog disappears immediately.
If dialog is CControlDialog your main window?
Did you select any styles in dialog editor?
It is very weird that your dialog disappears immediately.
ASKER
ok..hehe..sorry about the wait..but i just figured it out..
MeasurementThreadHandle = AfxBeginThread(CMeasuremen tThread, HandleArray)->m_hThread;
CControlDialog dlg(HandleArray, MeasurementThreadHandle);
BOOL check = dlg.Create((UINT)IDD_CONTR OL, AfxGetMainWnd());
//check = dlg.ShowWindow(SW_SHOW);
while (WaitForSingleObject(Measu rementThre adHandle, 0) == WAIT_OBJECT_0)
{
while (PeekMessage(&msg, NULL, 0, 0, 0))
{
GetMessage(&msg, 0, 0,0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
dlg.DestroyWindow();
The destroy window is called...i don't even go into the while loop..any ideas??
MeasurementThreadHandle = AfxBeginThread(CMeasuremen
CControlDialog dlg(HandleArray, MeasurementThreadHandle);
BOOL check = dlg.Create((UINT)IDD_CONTR
//check = dlg.ShowWindow(SW_SHOW);
while (WaitForSingleObject(Measu
{
while (PeekMessage(&msg, NULL, 0, 0, 0))
{
GetMessage(&msg, 0, 0,0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
dlg.DestroyWindow();
The destroy window is called...i don't even go into the while loop..any ideas??
Condition!!!
while (WaitForSingleObject(Measu rementThre adHandle, 0) != WAIT_OBJECT_0)
if WaitForSingleObject returns WAIT_OBJECT_0 it means that the object was in signaled state (i.e. thread finished). So, you want your loop running till you get WAIT_OBJECT_0.
while (WaitForSingleObject(Measu
if WaitForSingleObject returns WAIT_OBJECT_0 it means that the object was in signaled state (i.e. thread finished). So, you want your loop running till you get WAIT_OBJECT_0.
ASKER
OK...I tried that..but after I call AfxThreadExit(0) on the other thread...it still doesn't work...It is never signaled
ASKER
OK..i got it..i had been autodeleteing the thread...so it didn't signal...how do i delete a thread...with a handle to it???
ASKER
also...how do i make the dialog box the only thing that can be clicked on..
i don't want the user to be able to interact with the rest of the program..
i don't want the user to be able to interact with the rest of the program..
ASKER
It all works...just a few more things..
1) Thank you VERY much for helping
2) The dialog box will not move when i move the main window. I can make it move with the window, but when i move the main window the smaller window does not get back the focus.
3) Is there a way to make the rest of my program not "work" like in a modal dialog box. I only want the user to be able to click on the dialog box not anything else.
Thanks once again
1) Thank you VERY much for helping
2) The dialog box will not move when i move the main window. I can make it move with the window, but when i move the main window the smaller window does not get back the focus.
3) Is there a way to make the rest of my program not "work" like in a modal dialog box. I only want the user to be able to click on the dialog box not anything else.
Thanks once again
To end the thread simply quit your thread function.
You can disable application main window by calling:
AfxGetMainWnd ()->EnableWindow (FALSE);
and enable it by calling:
AfxGetMainWnd ()->EnableWindow (TRUE);
You can disable application main window by calling:
AfxGetMainWnd ()->EnableWindow (FALSE);
and enable it by calling:
AfxGetMainWnd ()->EnableWindow (TRUE);
ASKER
PMazur..Thank you for the help...I don't think that i have any more questions....but i might later on...You just helped me complete my first MFC program..wow..three months ago i didn't know there was a thing called MFC..now i know there is a whole bunch of MFC stuff i don't know :)...thanks for helping me finish off my project...
How did you get to know MFC?
How did you get to know MFC?
I am glad to hear that.
>>How did you get to know MFC?
It was a long time ago. Basically from Microsoft's documentation and from MFC's source code and samples. And of course from using it, that's the best way.
>>How did you get to know MFC?
It was a long time ago. Basically from Microsoft's documentation and from MFC's source code and samples. And of course from using it, that's the best way.
ASKER