2016-07-25 14 views
0

我有一些unmanged代碼移植到VC100中。我正在嘗試使用定時器以間隔模式運行成員函數。這個類正在使用設計模式私有類數據。我不確定如何設置回撥。我曾嘗試如何發送私有數據類的成員函數作爲C++中的線程的回調非託管?

class IProcessable { 
    public: 
     virtual void process() throw() = 0; 

    protected: 
     IProcessable() throw() {} 
     virtual ~IProcessable() throw() {} 
    }; 

class Processor::Private { 
    private: 
     IProcessable & mProcessable; 
    public: 
     Private(IProcessable & processable, 
      unsigned int interval_ms) throw() : 
      mProcessable(processable) 
     { 
      CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(this->callTimer), 0, 0, NULL); 
      // I want to send the callTimer to be called at the interval.. 
      onTimer(); 
     } 

     __fastcall ~Private() throw() { 
     } 
     void callTimer() 
     { 
      mProcessable.process(); 
     } 
    private: 
     void __fastcall onTimer() { 
      mProcessable.process(); 
     } 

    }; 

    Processor::Processor(IProcessable & processable, unsigned int interval_ms) throw() : 
     mPrivate(new Private(processable, interval_ms)) {} 

    Processor::~Processor() throw() { 
     delete mPrivate; 
    } 
} 

錯誤C2440: '類型轉換':無法從 '重載函數' 到 'LPTHREAD_START_ROUTINE' 轉換

+0

如果您使用的是vc100,請使用'noexcept'而不是'throw()'。 – kfsone

回答

0

callTimer成員功能,它需要一個this上下文來知道它正在運行的類的哪個實例。

LPTHREAD_START_ROUTINE需要一個函數,它接受LPVOID(void *)參數並返回一個DWORD,callTimer不接受任何參數並且不返回。

你需要的是一個蹦牀靜態函數,它接受一個類的實例,並轉發給相應的成員函數:

CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(this->callTimerIf), (void*)this, 0, NULL); 

和(這是私人的成員):

static DWORD callTimerIf(void* instance) 
{ 
    Private* pvt = (Processor::Private*)instance; 
    pvt->callTimer(); 
    return 0; 
} 
0

callTimer是一種類方法。它有一個隱藏的this參數,所以看起來在C工作的廣告,如果你是路過,看起來像

void (*) (Processor * this) 

,而不是

DWORD (*) (LPVOID lpThreadParameter) 

所以,你需要做的是類似的功能這樣的:

class Processor::Private { 
    private: 
     IProcessable & mProcessable; 
    public: 
     Private(IProcessable & processable, 
      unsigned int interval_ms) throw() : 
      mProcessable(processable) 
     { 
      CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(&callTimer), this, 0, NULL); 
      onTimer(); 
     } 

     __fastcall ~Private() throw() { 
     } 
     static DWORD callTimer(LPVOID lpThreadParameter) 
     { 
      Private * priv = (Private *)lpThreadParameter; 
      priv->mProcessable.process(); 
      return 0; // or whatever makes sense 
     } 
    private: 
     void __fastcall onTimer() { 
      mProcessable.process(); 
     } 

    }; 

重要變化1:

static DWORD callTimer(LPVOID lpThreadParameter) 

callTimer方法現在是靜態的,不需要調用任何對象。所以沒有this參數。相反,this被隱藏起來爲lpThreadParameter,並將其轉換爲Private *以調用我們真正想調用的函數。它也匹配LPTHREAD_START_ROUTINE所要求的原型。

重要變化2:

CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(&callTimer), this, 0, NULL); 

經過的現在靜態callTimer方法和this地址爲lpParameter一遍以後作爲lpThreadParameter將會出現。

獲得正確的時機是另一個問題,但如果你打算使用這種架構,你可能需要一個Waitable Timer

其他方法仍然使用Waitable Timer,但通過Overlapped IO使用它,可以幫助您使程序更容易同步。

相關問題