2013-03-24 22 views
6

Belirli bir kimlik işleminin ana (yalnızca) iş parçacığı kimliğini bulmama yardımcı olabilir misiniz, lütfen?Bir işlemin ana iş parçacığı kimliği nasıl alınır (kimliğiyle bilinir)?

Görev bağlamı: Bir işlem, (şimdilik) penceresiz, ancak bir (bazı) iş parçacığı içeriyor.

İstenilen: WM_QUIT sadece ana iş parçacığına gönderiliyor.

İstem dışı: TerminateProcess kullanımı veya WM_QUIT'u birincil olmayan iş parçacıklarına gönderme.

cevap

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

İyi görünüyor, teşekkürler! –

+6

Bu cevap, kodun ne yaptığı ve nasıl çalıştığı hakkında bir açıklama içeriyorsa daha iyi olurdu. Özellikle, bu işlemin birden çok iş parçacığı olduğu durumda, "ana" iş parçacığının belirli bir işlemin ne olduğunu nasıl belirliyorsunuz? Bana, iş parçacığının yaratma zamanına dayanıyormuşsun gibi geliyor. Bu mutlaka güvenilir bir sezgisel değil; İnsanların bu yaklaşımın avantajlarını ve dezavantajlarını dikkatlice değerlendirebildiklerini belirtmek önemlidir. * Sadece * kodu içeren cevaplar cevap değildir. –

2

Belirli bir konuya mesaj gönderemezsiniz. Mesajlar sıraya konur ve sadece ana iş parçacığından işlenir.

Eğer bir kullanıcı arayüzü vardır pencereler süreci kapatmak using sendmessage to send wm_close to another process

+0

Ben kullanışlı olarak cevabınızı işaretler, Cevabınız için teşekkür ederiz (Benim uygulamada öncelikle ihtiyaç). –

+3

Aslında, her biri farklı bir iş parçacığıyla ilişkilendirilmiş birden çok ileti sırası olabilir ve varsa, belirli bir iş parçacığına bir ileti göndermek için PostThreadMessage'ı kullanabilirsiniz. –

+0

@Harry: Bu bilmek ilginç! Birden fazla kuyruk mevcut olduğunda gerçekçi kullanım durumu nedir? – alex

4

A ana dişin diş kimliği almak için daha basit ve daha emin bir yol bakmak isterseniz ana iş parçacığı kaydeden izin vermektir onun

MainThreadId_G = ::GetCurrentThreadId(); 

ardından diğer konuları, Arayabileceğin: sizin WinMain ya da bir yere senin 'ana iş parçacığı' başında belki de paylaşılan genel değişkeni içine ::GetCurrentThreadId() kullanarak kendi iş parçacığı kimliği ::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);

+0

Bu cevabı kesinlikle tercih ediyorum. Özlü, tam bir cevap ve iyi bir açıklama sağlar. Elbette, global bir değişken kullanmak yerine, ana iş parçacığı kimliğini, oluşturulduğunda çalışan iş parçacığına bir parametre olarak iletmek mümkündür. –

1

Bu MFC nasıl işleneceğini kontrol ettik ve UI iş parçacığı yapıcısı belirlenir benziyor:

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

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

    m_nThreadID = ::GetCurrentThreadId(); 

Ve UI iş parçacığı kimliği anlayabiliriz MFC çağrısı AfxGetApp()->m_nThreadID kullanarak.

Ancak - .dll ana iş parçacığından yüklenmemişse bu yaklaşım çalışmaz - daha sonra MFC'nin yaklaşımı çalışmaz - AfxGetApp()->m_nThreadID ana iş parçacığından başka bir şey döndürür.

Ancak genellikle .dll dosyanız ana iş parçacığından yüklenir, ancak .dll dosyanız gerekli değildir. Böyle bir yaklaşım tavsiye verebilecek ettik:

.dll ana UI iş parçacığı tarafından yüklenirse
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 

, sen yapıcı çağrısı (GetMainThread sınıfı) doğru iplik kodu oluşturulacaktır. Eğer onlara ihtiyacım yok

Kaldır AfxGetApp() aramaları eğer

İlgili konular