2011-06-09 15 views
5

मैं निश्चित रूप से CreateThread फ़ंक्शन के लिए एक पॉइंटर पास नहीं कर सकता। मुझे क्या करना चाहिए?विंडोज थ्रेड - विंडोज़ में एक थ्रेड फ़ंक्शन कैसे करें?

+0

संभावित डुप्लिकेट [सी ++ में थ्रेडिंग का सरल उदाहरण] (http://stackoverflow.com/questions/266168/simple-example-of-threading-in-c) –

+0

सावधानी के साथ CreateThread का उपयोग करें, क्योंकि यह नहीं है नए धागे के लिए सी (और संभवतः सी ++) रनटाइम प्रारंभ करें। –

+0

वास्तव में? रनटाइम मैन्युअल रूप से कैसे प्रारंभ करें? – KOLANICH

उत्तर

4

सबसे आम तरीका एक थ्रेड क्लास बनाना है जिसमें रन() विधि और प्रारंभ() विधि (ये नाम जावा थ्रेड क्लास से उधार लेते हैं)। रन() एक शुद्ध आभासी है जिसे आप वास्तविक काम करने के लिए थ्रेड से व्युत्पन्न कक्षा में अधिभारित करते हैं। विधि प्रारंभ() आंतरिक रूप से Reinterpret_cast से void * के माध्यम से इस पॉइंटर को पास करने के द्वारा CreateThread को कॉल करता है। थ्रेड क्लास में थ्रेड एंटरपॉइंट() स्थैतिक फ़ंक्शन भी है जिसे आप CreateThread पर पास करते हैं। ThreadEntryPoint() में आप एक reinterpret_cast वापस थ्रेड * करते हैं और फिर उस पर रन() को कॉल करें।

यदि कोई ऐसी स्थिति है जिसमें आप एक अलग वर्ग की विधि को अलग थ्रेड पर निष्पादित करने के लिए चाहते हैं (थ्रेड क्लास से प्राप्त किए बिना) आप एक थ्रेड-व्युत्पन्न कक्षा बना सकते हैं जो एक जोड़ी ऑब्जेक्ट + विधि प्राप्त करता है कन्स्ट्रक्टर में पॉइंटर्स, और उन्हें चलाने में कॉल()। चीजों को कम करने के लिए, इस व्युत्पन्न वर्ग को एक टेम्पलेट बनाएं। मज़ेदार एडाप्टर के लिए भी बढ़ावा देने पर एक नज़र डालें।

+0

धन्यवाद। जैसा कि मैंने समझा, मैं केवल अपनी कक्षा में एक स्थिर कार्य जोड़ने और शुरू करने के लिए एक विधि जोड़ने के लिए nedd, थ्रेड एंटरपॉइंट कार्यक्षमता statiс विधि में महसूस किया जाएगा। – KOLANICH

+0

हां, यदि आप इसे एक बार करना चाहते हैं-केवल इतना ही सरल है। यदि आप इसे अन्य स्थानों पर पुन: उपयोग करना चाहते हैं, तो अलग वर्ग में कोड को अलग करना बेहतर होगा। –

7

एक वर्ग का उपयोग कर, इस तरह कुछ पैटर्न आम तौर पर अच्छी तरह से काम करता है:

static UINT __cdecl StaticThreadFunc(LPVOID pParam); 
UINT ThreadFunc(); 

सीपीपी

// Somewhere you launch the thread 
AfxBeginThread(
    StaticThreadFunc, 
    this); 

UINT __cdecl CYourClass::StaticThreadFunc(LPVOID pParam) 
{ 
    CYourClass *pYourClass = reinterpret_cast<CYourClass*>(pParam); 
    UINT retCode = pYourClass->ThreadFunc(); 

    return retCode; 
} 

UINT CYourClass::ThreadFunc() 
{ 
    // Do your thing, this thread now has access to all the classes member variables 
} 
5

मैं अक्सर ऐसा करते हैं:

class X { 
private: 
    static unsigned __stdcall ThreadEntry(void* pUserData) { 
     return ((X*)pUserData)->ThreadMain(); 
    } 

    unsigned ThreadMain() { 
     ... 
    } 
}; 

और फिर मैंपास करता हूंधागा निर्माता कार्य करने के लिए उपयोगकर्ता डेटा के रूप में (_beginthread [पूर्व], CreateThread, आदि)

0

आप बात कर रहे हैं, तो के बारे में मूल निवासीCreateThread विधि आप शायद निम्नलिखित

CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&MyThreadProc,NULL,NULL,&threadId); 

कहाँ अपने कॉलबैक करने के लिए की आवश्यकता होगी विधि

void MyThreadProc() 
{ 
} 
+2

आप यह नहीं करना चाहते हैं - यहां कास्ट एक समस्या है: आम तौर पर बोलते हुए, आपको चीजों को काम करने के लिए कभी भी एक समारोह नहीं डालना चाहिए।इसके बजाय आपको बिना किसी कलाकार के MyThreadProc को पास करना होगा, और फिर MyWhreadProc() को DWORD WINAPI MyThreadProc (LPVOID) के रूप में बदलें, जो CreateThread की अपेक्षा कर रहा है। एक एपीआई की तुलना में एक अलग संख्या या पैराम या कॉलिंग कन्वेंशन के साथ एक फ़ंक्शन पास करने से उम्मीद है कि एक गड़बड़-अप स्टैक हो सकता है। – BrendanMcK

1

CreateThread किसी सदस्य फ़ंक्शन में पॉइंटर नहीं लेगी। आप सदस्य फ़ंक्शन को स्थिर फ़ंक्शन में लपेट सकते हैं जो ऑब्जेक्ट पॉइंटर को lpParameter के माध्यम से ले जाता है।

1

CreateThread के lpStartAddress प्रकार DWORD (WINAPI * PTHREAD_START_ROUTINE) (LPVOID lpThreadParameter) की है और इस सदस्य समारोह के साथ असंगत है के बाद से सदस्य समारोह एक अंतर्निहित इस अपने हस्ताक्षर में सूचक है। तो एक स्थैतिक फ़ंक्शन बनाएं और क्लास पॉइंटर को थ्रेड फ़ंक्शन के तर्क के रूप में पास करें।

संबंधित मुद्दे