Click to See Complete Forum and Search --> : How can I pass object to QueueUserWorkItem
mvujica
November 2nd, 2004, 09:36 AM
I have a class that sinks some COM ConnectionPoints events. It looks something like this:
STDMETHODIMP OnDataChange(
/* [in] */ DWORD dwCount,
/* [size_is][in] */ VARIANT __RPC_FAR *pvValues,
/* [size_is][in] */ FILETIME __RPC_FAR *pftTimeStamps,
/* [size_is][in] */ HRESULT __RPC_FAR *pErrors)
{
Now I want to do some processing with VARINAT ARRAY, which may take a long time to complete, so I want to dispatch that job to ThreadPool via QueueUserWorkItem. I created helper struct to hold these pointers and pass it to QueueUserWorkItem lpParameter.
It is not working every time because passed VARIANT pointer in ThreadProc is sometimes <bad_pointer>????
FILETIME and HRESULT arrays are fine
I need help on this please.
:cry:
marten_range
November 2nd, 2004, 10:11 AM
Without knowing exactly what you code is like it can be a bit hard to deduce what the error is. However, I might take a qualified guess.
In short:
You need to make a deep copy of the VARIANT array. That is you need to allocate your own VARIANT array and for each VARIANT in the in array you execute VariantCopy (see the platform SDK), This new array you pass to your worker thread which now assumes the control its lifetime.
Explaination:
The caller controls the life time of the VARIANT array. After you dispatched the pointer to the variant array to the thread proc and returns from the event sink the caller (the code that fired the event) will delete the variant array. This would explain why you sometimes get <bad pointer>.
mvujica
November 3rd, 2004, 01:25 AM
Well I copied VARIANT array but I used ::VariantCopy on the whole array and as the PlatformSDK says: "If pvargSrc is a VT_BSTR, a copy of the string is made. If pvargSrc is a VT_ARRAY, the entire array is copied." I figured that will work but it didn't.
mvujica
November 3rd, 2004, 04:53 AM
I need some additional help on "deep" variant copying. I have helper class and I'm doing this:
STDMETHODIMP OnDataChange(
/* [in] */ DWORD dwCount,
/* [size_is][in] */ VARIANT __RPC_FAR *pvValues,
/* [size_is][in] */ FILETIME __RPC_FAR *pftTimeStamps,
/* [size_is][in] */ HRESULT __RPC_FAR *pErrors)
{
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = dwCount;
SAFEARRAY * psa;
psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
::SafeArrayCopyData(V_ARRAY(pvValues), psa);
pthreaddata=new CWorkData();
pthreaddata->dwCount=dwCount;
pthreaddata->pftTimeStamps=pftTimeStamps;
pthreaddata->pErrors=pErrors;
V_ARRAY(pthreaddata->pvValues)=psa;
::QueueUserWorkItem((LPTHREAD_START_ROUTINE)LongToExecuteFunc,pthreaddata,WT_EXECUTEDEFAULT);
return S_OK;
}
Now I get <bad_pointer> every time!!! :cry:
Arjay
November 17th, 2004, 12:46 PM
Are you sure that pthreaddata is valid over the lifetime of QueueUserWorkItem()? If you are creating this on the stack (or it's otherwise getting deleted), it could become invalid before QUWI completes.
Arjay
mvujica
November 22nd, 2004, 08:41 AM
Yes! That was the problem. :blush:
Well I had solved it by using ATL Global List of pthreaddata pointers and with ATL ComVariant classes inside pthreaddata along others.
Is there a better solution then global list?
Marko.
Arjay
November 22nd, 2004, 12:45 PM
Is there a better solution then global list?
There might be a better solution, but I'm having a bit of trouble understanding the overall architecture enough to offer an alternative. Could you post some sample code?
mvujica
November 24th, 2004, 04:26 AM
Well I've just realized that I'm a complete dumbass, and I could save myself couple of days of wandering, but I still need your help: since my class is COM class that sinks some COM events (one is onDataChange) I now know that I don't have to create my own threadpool and deal with variant and poiner storing in global list (there go my days :cry: )but there is a ATL COM mechanism of runing sink class method in threadpool.
I mean inheriting from CAtlAutoThreadModule and using DECLARE_CLASSFACTORY_AUTO_THREAD macro in class. Since this is all very new to me I could use some clarification please.
So I am writing a COM MTA client that sinks Connectionpoint events and onDataChange has to be able to recive multiple events simultaneously.
mvujica
November 25th, 2004, 06:31 AM
Sadly, I can not make that "CAtlAutoThreadModule and using DECLARE_CLASSFACTORY_AUTO_THREAD" approach work.
For now I'm back to QueueUserWorkItem.
Can anyone help me?
Thanks....
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.