In AvgOpt.h, add an instance of ThreadManager.:
... #include <xlserialize.h> #include <xlmenu.h> #include "ThreadManager.h" #include "data_avgopt.h" ... class CAvgOptApp : public CXllApp { public: CAvgOptApp(); // Names public: static LPCSTR m_pszDefName; // Data AvgOptDataCache m_cacheAvgOpt; // Operations void ClearCache(); // Multiple thread manager psl::ThreadManager m_threadManager; static size_t m_maxThreads; // Menu CXlMenu m_menu; ... };
In AvgOpt.cpp, amend the constructor, so that the ThreadManager instance is initialized.
///////////////////////////////////////////////////////////////////////////// // CAvgOptApp construction size_t CAvgOptApp::m_maxThreads = 4; CAvgOptApp::CAvgOptApp() : m_threadManager(m_maxThreads) { // TODO: add construction code here, // Place all significant initialization in InitInstance }
Amend the OnXllOpenEx() and OnXllCose() event handlers, so that the ThreadManager is initialized and terminated.
BOOL CAvgOptApp::OnXllOpenEx()
{
// Set up menu
m_menu.SetTexts("&AvgOpt");
m_menu.AddItem("&Clear cache", "AvgOptClearCache");
m_menu.Create();
// Start the thread manager
if (!m_threadManager.Init())
{
XlMessageBox("Failed to initialize thread manager",
XlMessageBoxTypeExclamation);
return FALSE;
}
return TRUE;
}
void CAvgOptApp::OnXllClose()
{
// Stop all threads
m_threadManager.Term();
// Delete menu
m_menu.Destroy();
}
Add a new function to be called by worker threads:
void __stdcall AvgOptValue_threadfn(void* pvData)
{
AvgOptData* args = (AvgOptData*)pvData;
args->Evaluate();
args->done = true;
psl::XllRtdSharedData::IncrementChannelSeqNum("AvgOpt");
}
The following points are of interest in the worker thread function:
__stdcall calling convention is required for the worker
thread."AvgOpt", and thereby informs the RTD
module that new data is available for this function.Next, we will modify the add-in function so that it passes all the work of calculation to a worker thread.