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.