免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
類成員函數(shù)作為多線程的入口函數(shù)的實(shí)現(xiàn)方法

通常在界面編程中,我們一方面要提供一個(gè)良好的界面環(huán)境給用戶,同時(shí)后臺(tái)還要做相關(guān)的應(yīng)用處理,比如對(duì)數(shù)據(jù)庫的查詢、更新;復(fù)雜的計(jì)算處理。而這往往是很耗時(shí)的,如果界面更新和后臺(tái)處理在同一個(gè)主線程中,那么界面的更新將受到后臺(tái)處理程序的影響,特別是當(dāng)后臺(tái)程序比較耗時(shí)時(shí),界面往往得不到及時(shí)更新,會(huì)給用戶造成程序死掉的假象。對(duì)于這種情況,我們通常會(huì)采用多線程編程的方式來實(shí)現(xiàn),即響應(yīng)用戶的操作在一個(gè)線程,而用戶后臺(tái)處理在另外一個(gè)線程。

在有些時(shí)候,我們要新開一個(gè)線程,在這個(gè)線程里面要訪問到類的成員函數(shù)和成員變量,但是CreateThread函數(shù)要求提供的線程函數(shù)必須是靜態(tài)成員函數(shù)或者全局函數(shù),這樣在線程里面是不能夠訪問到類的成員變量的。這就是一個(gè)比較麻煩的矛盾。
完整的方案如下

#include<windows.h>

#include<stdio.h>

#include<process.h>

class test

{

    int mx;

public:

    test(int x):mx(x){}

    static unsigned int __stdcall threadProc(void* pV) { test* p = (test*)pV;

        p->func();

        return 0;

    }

    void func()

    {

        printf("%d\n",mx);

    }

};

int main()

{

    test x(10);

    _beginthreadex(0,0,test::threadProc,(void*)&x,0,0);

或者m_hThread=CreateThread(NULL,NULL,CRealPlayer::MyFunction, (LPVOID)this,NULL,NULL);

    Sleep(100);

    return 0;

}
一種解決方案:將對(duì)象的this指針作為參數(shù)傳遞給線程函數(shù),然后在線程函數(shù)里面將其轉(zhuǎn)換為相應(yīng)的類對(duì)象指針,在里面調(diào)用指針進(jìn)行相應(yīng)的操作就OK了。

相應(yīng)的例子如下:

1.在這里創(chuàng)建新的線程,將this指針傳遞給線程函數(shù) MyFunction

m_hThread=CreateThread(NULL,NULL,CRealPlayer::MyFunction, (LPVOID)this,NULL,NULL);

2.//線程函數(shù),在線程里面實(shí)現(xiàn)將CRealPlayer的member2和member3成員

相加,結(jié)果放到成員member1中。



這個(gè)線程函數(shù)是 static的成員函數(shù)。
DWORD WINAPI CRealPlayer::MyFunction(LPVOID lpParameter)
{

CRealPlayer * lp=(CRealPlayer *)lpParameter;

lp->member1=lp->member2+lp->member3;

}

多線程在很多地方都有講述,但大都作為全局函數(shù),且不能對(duì)類的成員進(jìn)行訪問,本文講述如何將一個(gè)線程定義在一個(gè)類中以及如何通過這個(gè)線程實(shí)現(xiàn)對(duì)類中的成員進(jìn)行訪問。

多線程創(chuàng)建線程時(shí),線程函數(shù)如果要設(shè)置成類的成員函數(shù),則必須是靜態(tài)成員函數(shù),在此函數(shù)種不能使用非靜態(tài)成員變量,如果要使用非靜態(tài)成員變量,則一種比較適合線程的方法是:建立線程的時(shí)候把this作為CreateThread的一個(gè)參數(shù)(即第4個(gè)參數(shù),就是那個(gè)LPVOID型的),然后線程里就對(duì)應(yīng)pParam,例如:
        static UINT ThreadProc(LPVOID pParam)  
        {  
                Your_Class *p=(Your_Class *)pParam;  
                //然后用p間接使用成員變量。 
        }           線程函數(shù)是回調(diào)函數(shù),因此它必須是靜態(tài)成員函數(shù)或者是類外部聲明的全局函數(shù)。 函數(shù)在類中的定義

在類中,多線程函數(shù)必須定義為靜態(tài)函數(shù)

Class CMutilThread: Public CDialog

{

………

private:

HANDLE          hThread;

DWORD           idThread;

UINT            couter;

protected:

public:

static       DWORD  WINAPI  ThreadPro(LPVOID lpParam);

};

  • 多線程的實(shí)現(xiàn)

多線程函數(shù)的實(shí)現(xiàn)(本例中每次線程被調(diào)用的時(shí)候均對(duì)計(jì)數(shù)器加1)

DWORD WINAPI CMutilThread(LPVOID)

{

CMutilThread  *pDlg = (CMutilThread*)lpParam;//定義指向本類的指針,相當(dāng)于this 

pDlg->couter++;    //計(jì)數(shù)器加1

}

多線程函數(shù)的創(chuàng)建

void CMutiThread::OnStart()

{

hThread = CreateThread (NULL, 0,THreadPro,this,0,idThread);

}

多線程的終止

void CMutiThread::OnEnd()

{

TerminalThread(hThread,0);

}

//*******************************************************************************************************************************

C++類成員函數(shù)直接作為線程回調(diào)函數(shù)

以前寫線程時(shí)要么老老實(shí)實(shí)照著聲明寫,要么使用C++類的靜態(tài)成員函數(shù)來作為回調(diào)函數(shù),經(jīng)常會(huì)因?yàn)榫€程代碼而破壞封裝.之前雖然知道類成員函數(shù)的展開形式,但從沒想過利用過它,昨天看深入ATL時(shí)無意中學(xué)會(huì)了這一招:)

類成員方法是一個(gè)比較特殊的函數(shù),它在編譯時(shí)會(huì)被轉(zhuǎn)化成普通函數(shù),比如有TMyClass類:
class TMyClass{
    void Func();
};

這個(gè)TMyClass::Func最終會(huì)轉(zhuǎn)化成 void Func(TMyClass *this); 也就是說在原第一個(gè)參數(shù)前插入指向?qū)ο蟊旧淼膖his指針。

我們可以利用這個(gè)特性寫一個(gè)非靜態(tài)類成員方法來直接作為線程回調(diào)函數(shù),先看_beginthread函數(shù)的定義:
unsigned long _RTLENTRY _EXPFUNC _beginthread (void (_USERENTRY *__start)(void *),unsigned __stksize, void *__arg);
其中的第一個(gè)參數(shù)就是作為線程執(zhí)行主體的回調(diào)函數(shù)。它的原型是:void Func(void *),這個(gè)void*參數(shù)是作為自定義數(shù)據(jù)傳入的。對(duì)比一下上面所說的TMyClass::Func的最終形式,它正好可以符合這里的要求。

現(xiàn)在做個(gè)實(shí)驗(yàn):
#include <stdio.h>
#include <process.h>

class TMyClass{
    int m_nCount;
    int m_nId;
public:
    TMyClass(int nId,int nCount)
        :m_nId(nId),m_nCount(nCount)
    {
    }

    void _USERENTRY ThreadProc()            // 類成員方法
    {
        for(int i=0; i <m_nCount; i++)      // 根據(jù)m_nCount成員打印一排數(shù)字
        {
            printf("Class%d : %d\n",m_nId,i);
        }
    }
};

int main(int argc, char* argv[])
{
    union {                                // 聯(lián)合類,用于轉(zhuǎn)換類成員方法指針到普通函數(shù)指針(試過編譯器不允許在這兩種函數(shù)之間強(qiáng)制轉(zhuǎn)換),不知道有沒有更好的方法。
        void (_USERENTRY *ThreadProc)(void *);
        void (_USERENTRY TMyClass::*MemberProc)();
    } Proc;                                // 盡管聯(lián)合里的兩種函數(shù)類型現(xiàn)在看起來有很大不同,但它們的最終形式是相同的。

    TMyClass MyClass1(1,10),MyClass2(2,5); // 產(chǎn)生兩個(gè)TMyClass對(duì)象

    Proc.MemberProc = &TMyClass::ThreadProc;  // 轉(zhuǎn)換,Proc.ThreadProc就是對(duì)應(yīng)的普通函數(shù)指針了

    _beginthread(Proc.ThreadProc,4096,&MyClass1);  // 開始線程,這里的Proc.ThreadProc實(shí)際上是TMyClass::ThreadProc, 它要的this指針是我們給的&MyClass1。
    _beginthread(Proc.ThreadProc,4096,&MyClass2);
    system("pause");
    return 0;
}

運(yùn)行!神奇吧?:-)

其實(shí)不止線程回調(diào)函數(shù),其實(shí)只要是形如Func(void*,...)的回調(diào)函數(shù)都可以用這種方法直接使用類成員方法。(前提是第一個(gè)void*是自定義數(shù)據(jù),也就是說它不能有其它功能)。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
多線程問題cannot convert parameter 3 from 'unsigned long (void *)' to 'unsigned long (
關(guān)于回調(diào)函數(shù)和this指針探討
C++中類成員函數(shù)作為回調(diào)函數(shù)
VC啟動(dòng)一個(gè)新線程的三種方法
Linux——線程編程
c#學(xué)習(xí)之易用的timer
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服