2013-03-24 9 views
6

क्या आप आईडी प्रक्रिया द्वारा दिए गए किसी भी मुख्य (केवल) थ्रेड आईडी को खोजने में मेरी सहायता कर सकते हैं?किसी प्रक्रिया की मुख्य थ्रेड आईडी कैसे प्राप्त करें (इसकी आईडी द्वारा ज्ञात)?

कार्य संदर्भ: एक चल रही प्रक्रिया (फिलहाल) कोई खिड़कियां नहीं है लेकिन कुछ (कुछ) धागे हैं।

चाहता था: WM_QUIT को केवल मुख्य धागे पर पोस्ट करना।

नहीं चाहता था: TerminateProcess का उपयोग या गैर-प्राथमिक थ्रेड पर WM_QUIT पोस्ट करना।

उत्तर

6
#ifndef MAKEULONGLONG 
#define MAKEULONGLONG(ldw, hdw) ((ULONGLONG(hdw) << 32) | ((ldw) & 0xFFFFFFFF)) 
#endif 

#ifndef MAXULONGLONG 
#define MAXULONGLONG ((ULONGLONG)~((ULONGLONG)0)) 
#endif 

bool CloseProcessMainThread(DWORD dwProcID) 
{ 
    DWORD dwMainThreadID = 0; 
    ULONGLONG ullMinCreateTime = MAXULONGLONG; 

    HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 
    if (hThreadSnap != INVALID_HANDLE_VALUE) { 
    THREADENTRY32 th32; 
    th32.dwSize = sizeof(THREADENTRY32); 
    BOOL bOK = TRUE; 
    for (bOK = Thread32First(hThreadSnap, &th32); bOK; 
     bOK = Thread32Next(hThreadSnap, &th32)) { 
     if (th32.th32OwnerProcessID == dwProcID) { 
     HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, 
            TRUE, th32.th32ThreadID); 
     if (hThread) { 
      FILETIME afTimes[4] = {0}; 
      if (GetThreadTimes(hThread, 
          &afTimes[0], &afTimes[1], &afTimes[2], &afTimes[3])) { 
      ULONGLONG ullTest = MAKEULONGLONG(afTimes[0].dwLowDateTime, 
               afTimes[0].dwHighDateTime); 
      if (ullTest && ullTest < ullMinCreateTime) { 
       ullMinCreateTime = ullTest; 
       dwMainThreadID = th32.th32ThreadID; // let it be main... :) 
      } 
      } 
      CloseHandle(hThread); 
     } 
     } 
    } 
#ifndef UNDER_CE 
    CloseHandle(hThreadSnap); 
#else 
    CloseToolhelp32Snapshot(hThreadSnap); 
#endif 
    } 

    if (dwMainThreadID) { 
    PostThreadMessage(dwMainThreadID, WM_QUIT, 0, 0); // close your eyes... 
    } 

    return (0 != dwMainThreadID); 
} 
+1

अच्छा लग रहा है, धन्यवाद! –

+6

यह उत्तर बेहतर होगा अगर इसमें कोड के बारे में कुछ स्पष्टीकरण शामिल है और यह कैसे काम करता है। विशेष रूप से, आप यह निर्धारित कर रहे हैं कि "मुख्य" थ्रेड उस मामले में किसी विशेष प्रक्रिया का क्या है जहां उस प्रक्रिया में एकाधिक धागे हैं? ऐसा लगता है कि आप इसे थ्रेड के निर्माण समय पर आधारित कर रहे हैं। यह जरूरी नहीं है कि एक विश्वसनीय ह्युरिस्टिक; यह इंगित करना महत्वपूर्ण है कि लोग इस दृष्टिकोण के फायदे और नुकसान सावधानी से विचार कर सकते हैं। उत्तर जिनमें केवल * कोड होता है, वे उत्तर नहीं हैं। –

2

आप एक विशिष्ट धागे को संदेश पोस्ट नहीं कर सकते हैं। संदेशों को कतार में रखा जाता है, और केवल मुख्य धागे से संसाधित होते हैं।

आप, खिड़कियां प्रक्रिया यूआई है कि बंद using sendmessage to send wm_close to another process

+0

अपने जवाब के लिए धन्यवाद, मैं उपयोगी के रूप में अपने जवाब का प्रतीक होगा। –

+3

असल में, कई संदेश कतार हो सकते हैं, प्रत्येक एक अलग थ्रेड से जुड़े होते हैं, और यदि वहां हैं, तो आप एक विशिष्ट थ्रेड को संदेश भेजने के लिए PostThreadMessage का उपयोग कर सकते हैं। –

+0

@ हैरी: यह जानना दिलचस्प है! यथार्थवादी उपयोग केस क्या है, जब एकाधिक कतार मौजूद होंगी? – alex

4

एक पर मुख्य थ्रेड के धागे आईडी प्राप्त करने के लिए बहुत सरल और surer तरीका एक बार देख ले चाहते हैं मुख्य थ्रेड रिकॉर्ड बताने के लिए है इसके खुद धागा आईडी अपने WinMain में या कहीं अपने 'मुख्य थ्रेड' के बहुत शुरुआत में शायद एक साझा वैश्विक चर में ::GetCurrentThreadId() का उपयोग कर,:

MainThreadId_G = ::GetCurrentThreadId(); 

फिर अपने अन्य धागे में, आप कॉल कर सकते हैं: ::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);

+0

मैं निश्चित रूप से इस उत्तर को पसंद करता हूं। संक्षिप्त, एक पूर्ण उत्तर, और एक अच्छी व्याख्या प्रदान करता है। बेशक, ग्लोबल वैरिएबल का उपयोग करने के बजाय, जब वे बनाए जाते हैं तो कार्यकर्ता-धागे के पैरामीटर के रूप में मुख्य थ्रेड आईडी को पास करना संभव है। –

1

मैं देख लिया है कि यह कैसे MFC में नियंत्रित किया जाता है, और यह यूआई धागे की तरह निर्माता से निर्धारित किया जाता है दिखता है:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc\appcore.cpp: 

CWinApp::CWinApp(LPCTSTR lpszAppName) 
{ 
... 

    m_nThreadID = ::GetCurrentThreadId(); 

और MFC कॉल AfxGetApp()->m_nThreadID का उपयोग कर आप यूआई धागा आईडी पता लगा सकते हैं।

हालांकि - यह दृष्टिकोण काम नहीं करता है अगर डीएलएल मुख्य धागे से नहीं लोड किया गया था - फिर भी एमएफसी का दृष्टिकोण काम नहीं करेगा - AfxGetApp()->m_nThreadID मुख्य धागे से कुछ और लौटाएगा।

लेकिन आम तौर पर आपका। डीएल मुख्य धागे से लोड हो जाता है, लेकिन आपका .dll आवश्यक एमएफसी सक्षम नहीं है। मैं इस तरह के दृष्टिकोण की सिफारिश कर सकता है है:

class GetMainThread 
{ 
public: 
    GetMainThread() 
    { 
     m_nThreadID = ::GetCurrentThreadId(); 
    } 

    DWORD m_nThreadID; 
}getMainThread; 


DWORD getUIThread() 
{ 
    DWORD id = 0; 

    if(AfxGetApp() != NULL) 
     id = AfxGetApp()->m_nThreadID; 
    else 
     id = getMainThread.m_nThreadID; 

    return id; 
} //getUIThread 

.dll मुख्य यूआई धागा द्वारा लोड किया जाता है, तो आप निर्माता कॉल (GetMainThread वर्ग) से सही धागा आईडी मिल जाएगा।

निकालें AfxGetApp() कॉल अगर तुम उन्हें जरूरत नहीं है (अपने आवेदन में मैं उन आवश्यक)

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