|
Thanks, good to know!
/Lazy Moak
|
|
|
|
|
I am using the original thread pool API provided by Windows (Not the latest one present in Vista and above) and I use QueueUserWorkItem[^] to submit new work to the queue.
After the threads start to execute and several work items are queued, is there any way with which I could find out the number of threads alive in the threadpool (including idle ones, if any)? I know that I can be monitoring this with tools like ProcessMonitor from sysinternals. But, that's not what I want. I'm not able to find something like GetThreadCount() the thread pool API.
I do understand that there is no need for me to know this, because the thread pool API guarantees to take care of dynamically creating or destroying threads depending on the work load and other criteria. However, I'm just curious.
Many thanks.
It is a crappy thing, but it's life -^ Carlo Pallini
|
|
|
|
|
Rajesh R Subramanian wrote: I was I'm not able to find something like GetThreadCount() the thread pool API.
The CreateToolhelp32Snapshot() function with TH32CS_SNAPTHREAD might be helpful. isnt it?
DWORD GetThreadCount()
{
THREADENTRY32 stThreadEntry = {0};
stThreadEntry.dwSize = sizeof( stThreadEntry );
HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( !Thread32First( hSnap, &stThreadEntry ))
{
return 0;
}
int nCount = 0;
DWORD dwCurrentProcessId = GetCurrentProcessId();
do
{
if( dwCurrentProcessId == stThreadEntry.th32OwnerProcessID )
{
nCount ++;
}
} while (Thread32Next(hSnap, &stThreadEntry ));
return nCount;
}
|
|
|
|
|
Hi Naveen,
Just wanted to quickly say thanks. I don't have VS installed, so I'll have to get back to the development machine to try it. On the other hand, it looks like this is going to return me the number of threads that my application is running. I'll be in a bit of yogurt in that case. I say it because there are threads started and being run from other modules as well (outside of the thread pool code, but within the app) and I want to be able to find the number of threads that specifically belong to the pool. I think I'll need to put in a bit more research.
But this is definitely a good start. Thanks again.
It is a crappy thing, but it's life -^ Carlo Pallini
|
|
|
|
|
Hi Rajesh,
Rajesh R Subramanian wrote: On the other hand, it looks like this is going to return me the number of threads that my application is running
ya. I thought if the module is small, you know the count of other threads. BTW where is the option to find out the thread pool's thread count in process explorer?
Rajesh R Subramanian wrote: I want to be able to find the number of threads that specifically belong to the pool. I think I'll need to put in a bit more research.
It's bit interesting. May be by checking the thread entry point we can decided whether the thread belongs to thread pool. How ever I don't know any direct method which returns the thread entry point. Stack walking may not work always if proper pdb files are not available. isnt it?
Any way if you come up with a method I would like to hear about it. Best wishes...
|
|
|
|
|
Naveen wrote: ya. I thought if the module is small, you know the count of other threads.
No, this is a fairly large project (even though the module that uses thread pools is relatively small). But of course yes, I can do my little test with a smaller dummy project.
Naveen wrote: BTW where is the option to find out the thread pool's thread count in process explorer?
There's no direct option as such, but the no. of threads that we create manually (as opposed to being managed by a pool managing algorithm driven by the OS), we have a count of it. Add 1 to it (the application's main thread). Now, we can subtract this number from the number of threads shown by process explorer for our process.
I was thinking of exploiting two things as well:
1. Entry point of the thread (like you said)
2. Do some experimenting with TLS (TLS won't work "properly" with pools, because any thread might execute the thread code, but TLS is guaranteed to be unique for a given thread).
I'll notify you if I post a reply here. But, I need to get some sleep now. I've had a long day.
It is a crappy thing, but it's life -^ Carlo Pallini
|
|
|
|
|
Hi,
I'm new to VC++. In C#, I used the event "DocEvents_ChangeEventHandler", to handle the cell changes in Excel file. Please guide me to handle the same in VC++.
Thanks in advance.
|
|
|
|
|
 Here's a complete example that fires up Excel and handles some application events - the general principle (registering an object with Excel to handle its events) will be exactly the same for document events, except you'll register the handler with the relevant workbook, I guess and have to change the event handler object to suit the DocEvents as opposed to AppEvents. As you're new to C++, I'd advise you get a little more familiar with C++ (and the Microsoft specific bits of VC++) before diving into this too deeply.
#include <atlbase.h>
#include <atlcom.h>
#import "libid:00020813-0000-0000-C000-000000000046" auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")
_ATL_FUNC_INFO SheetChangeInfo = { CC_CDECL, VT_EMPTY, 2, { VT_DISPATCH, VT_DISPATCH } };
_ATL_FUNC_INFO AfterCalculateInfo = { CC_CDECL, VT_EMPTY, 0, { } };
class ExcelAppEventHandler : public IDispEventSimpleImpl<1, ExcelAppEventHandler, &__uuidof(Excel::AppEvents)>
{
public:
ExcelAppEventHandler(bool& doneFlag) : done_(doneFlag) { done_ = false; }
BEGIN_SINK_MAP(ExcelAppEventHandler)
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x0000061c, &ExcelAppEventHandler::SheetChange, &SheetChangeInfo)
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x00000a34, &ExcelAppEventHandler::AfterCalculate, &AfterCalculateInfo)
END_SINK_MAP()
void _stdcall SheetChange(IDispatch *, struct Excel::Range *)
{
done_ = true;
}
void _stdcall AfterCalculate()
{
done_ = true;
}
private:
bool& done_;
};
int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(0, COINIT_MULTITHREADED);
{
Excel::_ApplicationPtr xl;
if (SUCCEEDED(xl.GetActiveObject(__uuidof(Excel::Application))))
{
xl->Workbooks->Add();
bool done = false;
ExcelAppEventHandler handler(done);
if (SUCCEEDED(handler.DispEventAdvise(xl)))
{
MSG msg;
while (!done && GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
handler.DispEventUnadvise(xl);
}
}
}
CoUninitialize();
return 0;
}
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Thank you so much. Your reply is very helpful.
|
|
|
|
|
I've added the following code in SheetChange function, to retrieve the data entered in excel cells.
void _stdcall SheetChange(IDispatch *, struct Excel::Range *target)
{
_bstr_t result= target->GetAddress(1,1,Excel::XlReferenceStyle::xlR1C1,1,1);
string str=result;
std::cout << "str is: " << str << "\n";
int index1 = str.find("!R");
int index2 = str.find("C");
string rowIndex = str.substr(index1+2);
string colIndex = str.substr(index2+1);
rowIndex = str.substr(index1+2);
colIndex = str.substr(index2+1);
int rIndex = atoi(rowIndex.c_str());
int cIndex = atoi(colIndex.c_str());
Excel::RangePtr rangePtr = target->Worksheet->Cells;
_variant_t vItem = rangePtr->Item[rIndex][cIndex];
_bstr_t bstrText( vItem );
cout << bstrText;
}
bstrText contains data in excel cell. where as its not retrieving the automatic changes.
for example, C1 cell contains the function =SUM(A1,B1), A1 = 10, B1=20 then C1=30
if I changed value in A1 to 15, at a time there will changes in two cell, i.e, A1(15) and C1(35).
I'm able to get the A1 value but not C1. How can I trace C1 value (automatic changes).
Please guide me to solve this.
Thanks in advance.
|
|
|
|
|
Has C1 actually changed? I would say not. It's formula has stayed the same. The documentation says that the SheetChange event is fired when a cell is changed by the user - you only change 1 cell, which is A1.
To catch when cells are recalculated, there's a Calculate event.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
C1 is getting changed as soon as A1 or B1 gets changed.
To catch when cells are recalculated, I added SheetCalculate event as below
_ATL_FUNC_INFO SheetCalculateInfo = { CC_CDECL, VT_EMPTY, 0, { VT_DISPATCH, VT_DISPATCH } };
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x00000a34, &ExcelAppEventHandler::SheetCalculate, &SheetCalculateInfo)
void _stdcall SheetCalculate(IDispatch *iDispatch)
{
cout << "Inside SheetCalculate" ;
}
When I changed function related cells, SheetCalculate function is not getting fired.
I think declaration of _ATL_FUNC_INFO SheetCalculateInfo is incorrect.
Please correct me to fire SheetCalculate function, to read the automatic cell changes.
|
|
|
|
|
SheetCalculate is a WorkBook event. You've put the SheetCalculate event signature in an Application event handler, judging by the mention of AppEvent all over the code. You would need a separate WorkBook event handler that you register (with DispEventAdvise) with the workbook you're interested in.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Thank you for your support. Can you give sample code around this.
and also it would be great if you can point me to complete documentation on interfacing Excel
|
|
|
|
|
Workbook SheetCalculate event handler:
_ATL_FUNC_INFO SheetCalculateInfo = { CC_CDECL, VT_EMPTY, 1, { VT_DISPATCH } };
class ExcelBookEventHandler : public IDispEventSimpleImpl<1, ExcelBookEventHandler, &__uuidof(Excel::WorkbookEvents)>
{
public:
BEGIN_SINK_MAP(ExcelBookEventHandler)
SINK_ENTRY_INFO(1, __uuidof(Excel::WorkbookEvents), 0x0000061b, &ExcelBookEventHandler::SheetCalculate, &SheetCalculateInfo)
END_SINK_MAP()
void _stdcall SheetCalculate(IDispatch *)
{
std::cout << "ExcelBookEventHandler::SheetCalculate\n";
}
};
Then given I have an Excel Application interface pointer called xl, I use this to register the event handler:
Excel::_WorkbookPtr wb = xl->Workbooks->Add();
ExcelBookEventHandler calc;
calc.DispEventAdvise(wb);
The same dispatch loop is used as I used before.
NarVish wrote: it would be great if you can point me to complete documentation on interfacing Excel
Not sure there IS any. The Excel help available through the VBA IDE tells you all about the Excel object model, and that's all you really need to know, except for some details (like dispids, etc) that I get by opening the Excel type library with the OLE/COM Object Viewer.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Thank you for your post.
SheetCalculate is getting fired whenever there is change in function related cells. My aim is to get the function result in excel. To get that I'm trying by calling different functions of iDispatch. But couldn't able to get the expected result.
void _stdcall SheetCalculate(IDispatch *iDispatch)
{
////////////*******GetIDsOfNames*******////////////
static DISPID dispid = 0;
wchar_t *ucName = L"Evaluate"; //I tried by giving "Run" and "Calculate" values in place of "Evaluate"
HRESULT result = iDispatch->GetIDsOfNames(IID_NULL, &ucName, 1,LOCALE_SYSTEM_DEFAULT, &dispid);
////////////*******Invoke*******////////////
VARIANT varResult;
DISPID dispid;
DISPID dispidNamed = DISPATCH_METHOD;
EXCEPINFO excep;
UINT uArgErr;
DISPPARAMS dispparams;
dispparams.cNamedArgs = 0;
dispparams.cArgs = 2;
dispparams.rgdispidNamedArgs = &dispidNamed;
HRESULT result = iDispatch->Invoke( odispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, &dispparams, &varResult, &excep, &uArgErr);
////////////*******GetTypeInfo*******////////////
ITypeInfo* pTypeInfo;
HRESULT result= iDispatch->GetTypeInfo(0,LOCALE_SYSTEM_DEFAULT,&pTypeInfo);
////////////*******GetTypeInfoCount*******////////////
UINT pct1;
HRESULT result= iDispatch->GetTypeInfoCount(&pct1);
////////////*******QueryInterface*******////////////
HRESULT result = iDispatch->QueryInterface(IID_IDispatch,(void**)&iDispatch);
}
I followed the below link to get some help.
"http://up.m-e-c.biz/up/books/Excel%20add-in%20C++.pdf"
|
|
|
|
|
Hi Stuart Dootson,
I implemented the cell change event functionality in C#.Net. Due to environmental dependencies, our project was shifted to VC++. and I'm new to C++. Please bear with me to solve the above post. A million thanks in advance...
|
|
|
|
|
Which event gets fired when a new Excel application is created. I handled NewWorkbook event of AppEvents. It gets triggered only when I create new excel workbook.
Please let me know which event handles the new Excel application instance.
Thanks in advance.
|
|
|
|
|
No such thing, AFAIK. What's the use case you're trying to solve?
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
my application reads data from Excel applications, which are opened. and it runs 24*7.. If any new excel application instance gets created and data entered by user, I need to read data from the new excel instance. So, I would like to handle the new excel application instance. from that event I can attach sheetchange and sheetCalculate events.
|
|
|
|
|
Is there any alternative idea to solve the above issue.
|
|
|
|
|
In my class, I have two classes ExcelAppEventHandler and ExcelBookEventHandler
AppHandler contains Sheetchange,WorkbookNewSheet and NewWorkbook events
BookHandler contains SheetCalculate event.
When I create a new worksheet, workbooknewsheet event occurs. in the new worksheet if I add some value, SheetChange event gets fired. Same way SheetCalculate should also be fired whenever calculations happend in the new sheet. classes are give below.
1. ExcelBookEventHandler bookHandler(done,xl);
2. bookHandler.DispEventAdvise(book);
1 and 2 statements are not working to call SheetCalculate event. Please let me know how to call SheetCalculate event from workbooknewsheet event.
class ExcelAppEventHandler : public IDispEventSimpleImpl<1, ExcelAppEventHandler, &__uuidof(Excel::AppEvents)>
{
public:
ExcelAppEventHandler(bool& doneFlag) : done_(doneFlag)
{
done_ = false;
}
BEGIN_SINK_MAP(ExcelAppEventHandler)
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x0000061c, &ExcelAppEventHandler::SheetChange, &SheetChangeInfo)
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x00000625, &ExcelAppEventHandler::WorkbookNewSheet, &WorkbookNewSheetInfo)
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x0000061d, &ExcelAppEventHandler::NewWorkbook, &NewWorkbookInfo)
END_SINK_MAP()
void _stdcall SheetChange(IDispatch *iDispatch, struct Excel::Range *target)
{
cout<<"Inside Sheet Change"<< endl;
}
void _stdcall NewWorkbook(Excel::_Workbook *book)
{
ExcelBookEventHandler bookHandler(done,xl);
bookHandler.DispEventAdvise(book);
}
void _stdcall WorkbookNewSheet(Excel::_Workbook *book, IDispatch *sh)
{
ExcelBookEventHandler bookHandler(done,xl);
bookHandler.DispEventAdvise(book);
}
}
class ExcelBookEventHandler : public IDispEventSimpleImpl<1, ExcelBookEventHandler, &__uuidof(Excel::WorkbookEvents)>
{
public:
ExcelBookEventHandler(bool& doneFlag,Excel::_ApplicationPtr xlApp) : done_(doneFlag),xlapPtr_(xlApp)
{
done_ = false;
}
BEGIN_SINK_MAP(ExcelBookEventHandler)
SINK_ENTRY_INFO(1, __uuidof(Excel::WorkbookEvents), 0x0000061b, &ExcelBookEventHandler::SheetCalculate, &SheetCalculateInfo)
END_SINK_MAP()
void _stdcall SheetCalculate(IDispatch *pDisp)
{
cout<< "Inside SheetCalculate";
}
}
|
|
|
|
|
Your code looks OK to me - I'm just not sure what you mean by "how to call SheetCalculate event from workbooknewsheet event".
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
If I add new workbook sheet, WorkbookNewSheet() event gets fired. If I enter some data in newly added sheet, SheetChange event is getting fired.
Likewise, if I add some function like =sum(10,20) in newly added sheet, SheetCalculate function should get fired. But its not happening. Had I missed any bind between appEventHandler and bookEventHandler?
Expected output is SheetCalculate (event of workbook) should get fired whenever there is a change in function result of the newly added WorkBookSheet.
Please let me know if my question is not clear.
|
|
|
|
|
 Firstly - be aware that Excel does dataflow analysis and will not call SheetCalculate if a change results in no recalculation (but as far as I can tell it ALWAYS calls AfterCalculate).
This (complete) program code successfully registers event handlers which get called by Excel:
#include <iostream>
#include <atlbase.h>
#include <atlcom.h>
#import "libid:00020813-0000-0000-C000-000000000046" auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")
_ATL_FUNC_INFO SheetChangeInfo = { CC_CDECL, VT_EMPTY, 2, { VT_DISPATCH, VT_DISPATCH } };
_ATL_FUNC_INFO AfterCalculateInfo = { CC_CDECL, VT_EMPTY, 0, { } };
class ExcelAppEventHandler : public IDispEventSimpleImpl<1, ExcelAppEventHandler, &__uuidof(Excel::AppEvents)>
{
public:
ExcelAppEventHandler(bool& doneFlag) : done_(doneFlag) { done_ = false; }
BEGIN_SINK_MAP(ExcelAppEventHandler)
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x0000061c, &ExcelAppEventHandler::SheetChange, &SheetChangeInfo)
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x00000a34, &ExcelAppEventHandler::AfterCalculate, &AfterCalculateInfo)
END_SINK_MAP()
void _stdcall SheetChange(IDispatch *, struct Excel::Range *)
{
std::cout << "ExcelAppEventHandler::SheetChange\n";
}
void _stdcall AfterCalculate()
{
std::cout << "ExcelAppEventHandler::AfterCalculate\n";
}
private:
bool& done_;
};
_ATL_FUNC_INFO SheetCalculateInfo = { CC_CDECL, VT_EMPTY, 1, { VT_DISPATCH } };
class ExcelBookEventHandler : public IDispEventSimpleImpl<1, ExcelBookEventHandler, &__uuidof(Excel::WorkbookEvents)>
{
public:
BEGIN_SINK_MAP(ExcelBookEventHandler)
SINK_ENTRY_INFO(1, __uuidof(Excel::WorkbookEvents), 0x0000061b, &ExcelBookEventHandler::SheetCalculate, &SheetCalculateInfo)
END_SINK_MAP()
void _stdcall SheetCalculate(IDispatch *)
{
std::cout << "ExcelBookEventHandler::SheetCalculate\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(0, COINIT_MULTITHREADED);
{
Excel::_ApplicationPtr xl;
if (SUCCEEDED(xl.GetActiveObject(__uuidof(Excel::Application))))
{
Excel::_WorkbookPtr wb = xl->Workbooks->Add();
ExcelBookEventHandler bookHandler;
bookHandler.DispEventAdvise(wb);
Excel::_WorksheetPtr ws = wb->Worksheets->Item[1];
if (ws)
std::cout << ws->Name << std::endl;
bool done = false;
ExcelAppEventHandler handler(done);
if (SUCCEEDED(handler.DispEventAdvise(xl)))
{
MSG msg;
while (!done && GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
handler.DispEventUnadvise(xl);
}
}
}
CoUninitialize();
return 0;
}
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|