Bir iş parçacığından iş parçacığı kimliğini alma


319

Örneğin iş parçacıklarının hatalarını ayıklarken C # 'da, her bir iş parçacığının kimliğini görebilirsiniz.

Programlı olarak aynı iş parçacığını almanın bir yolunu bulamadım. Hatta geçerli iş parçacığının kimliğini (özelliklerinde Thread.currentThread) alamadım .

Peki, Visual Studio iş parçacıklarının kimlikleri nasıl alır ve 2345mesela id ile iş parçacığının tutamacını almak için bir yolu var mı?

Yanıtlar:


437

GetThreadIdbelirli bir yerel iş parçacığının kimliğini döndürür. Yönetilen iş parçacıkları ile çalışmasını sağlamanın yolları vardır, eminim, tek yapmanız gereken iş parçacığı tutamacı ve bu işleve geçmek.

GetCurrentThreadId geçerli iş parçacığının kimliğini döndürür.

GetCurrentThreadId.NET 2.0'dan beri kullanımdan kaldırılmıştır: önerilen yol Thread.CurrentThread.ManagedThreadIdmülktür.


87
Bunu bulduğumdan, yazdığımdan ve daha sonra kullanımdan kaldırıldığı söylendiğinden, bunu yapmanın şu anki yolu Thread.CurrentThread.ManagedThreadId
James

3
ManagedThreadId, konuları ManagedThreadId özellik kimliği uygulamanız tarafından yeniden kullanıldığından tanımlamak için sağlam bir yaklaşım değildir. Bu nedenle, bazı senaryolarda iş parçacıkları için güvenilir bir tanımlayıcı değildir ve istisna ile karşılaşırsınız: "Aynı anahtara sahip bir öğe zaten eklenmiş." satırında ... İş parçacığını oluştururken benzersiz bir ad verin.
Forer

15
Bu yazıda çok kötü tavsiyeler var. Birkaç kişi bir iş parçacığını tanımlamak için "ManagedThreadId" kullanmanızı önerir. Tavsiyeyi kaldırmak için yazıyı düzenledim - çok azı işaret ettiğim şey farklı iplik kimlikleri. Yönetilen iş parçacığı kimlikleri, yönetilmeyen iş parçacığı kimlikleriyle aynı şey değildir ve insanlar bu kodu kopyalayıp yapıştırırlarsa, bazı çok ince eşitleme hataları oluşabilir. Thread sınıfı için MSDN'deki belgeler bu konuda çok açıktır. Notları sınıf düzeyinde görüntüleyin.
ShadowChaser

3
Kimliklerde senkronize olmuyorsunuz, muteks gibi senkronizasyon ilkellerini kullanıyorsunuz. Bu sadece hata ayıklama amaçlıdır.
Blindy

11
Ben System.Threading.Thread.CurrentThread.ManagedThreadIden azından a kullanırken işe yaramayacağını fark etmek için bu yorumu göndermek istiyorum SetWindowsHookEx. Bunun yerine yerel win32 işlevinden evre kimliğini almak zorundayız GetCurrentThreadId().
Kral Kral

82

Örneğin iş parçacıklarının hatalarını ayıklarken C # 'da, her bir iş parçacığının kimliğini görebilirsiniz.

Bu, yönetilen iş parçacıklarının kimliği olacaktır. ManagedThreadIdüyesidir, Threadböylece kimliği herhangi bir Thread nesnesinden alabilirsiniz. Bu size şu anki ManagedThreadID değerini verecektir :

Thread.CurrentThread.ManagedThreadId

Bir OS iş parçacığını OS iş parçacığı kimliğiyle (ManagedThreadID değil) almak için biraz linq deneyebilirsiniz.

int unmanagedId = 2345;
ProcessThread myThread = (from ProcessThread entry in Process.GetCurrentProcess().Threads
   where entry.Id == unmanagedId 
   select entry).First();

Yönetilen iş parçacıklarını numaralandırmanın ve ProcessThread ile İş parçacığı arasında bir ilişki bulunmadığı anlaşılıyor, bu nedenle ID tarafından yönetilen bir iş parçacığı almak zor bir iştir.

Yönetilen ve Yönetilmeyen iş parçacığı hakkında daha fazla bilgi için bu MSDN arcticle'a bakın .


4
Neden başka biri bu basit cevabı vermedi?
Stefan Steinegger

2
Bu çalışmıyor. GetCurrentProcess (). Threads, Threads'e dönüştürülemeyen bir ProcessThreadCollection döndürür. Kolay bir düzeltme görmüyorum.
mafu

2
@ mafutrct, cevap güncellendi. Bu özelliğe gerçekten .ProcessThreads! Teşekkürler.
badbod99

2
İki iş parçacığı kimliğinin farklı olduğunu daha net hale getirmek için bu yazının yeniden yazılmasını önerin. Birisi son cümleyi okuyamazsa, sadece ManagedThreadId'yi bağlar ve bunu ProcessThread.Id ile eşleştirmeye çalışır ve havok yaratır.
ShadowChaser

1
Farkı vurgulayan yararlı bir MSDN aktrisine bir bağlantı ekledim. Ancak, soru, hata ayıklama için iş parçacığı kimliğini almakla ilgili (bu durumda ManagedThreadID). İşletim sistemi ve yönetilen iş parçacıkları arasındaki farkın ayrıntılarıyla cevabı karmaşıklaştırmanın yararlı olduğunu düşünmüyorum.
badbod99

46

Kullanımdan kaldırılmış AppDomain.GetCurrentThreadIdiş parçacığının kimliğini almak için kullanımdan kaldırılmış kullanabilirsiniz . Bu yöntem, Win32 API yöntemine bir PInvoke kullanır GetCurrentThreadIDve Windows iş parçacığı kimliğini döndürür.

Bu yöntem, .NET Thread nesnesi tek bir Windows iş parçacığına karşılık gelmediğinden ve belirli bir .NET iş parçacığı için Windows tarafından döndürülebilen sabit bir kimlik olmadığından kullanımdan kaldırılmış olarak işaretlenir.

Bunun neden böyle olduğuna dair daha fazla neden için yapılandırıcının yanıtına bakın.


. Net Çekirdek 2.2, AppDomain.GetCurrentThreadId (ı Eski olarak MethodInfo aracılığıyla çağrılan) o notu ile DİKKAT Process.GetCurrentProcess () Lifler koleksiyonunu eşleştirme için yönetilen iplik numarası (yararsız döndürür.
brewmanz

32

İşletim sistemi kimliğini kullanmak için:

AppDomain.GetCurrentThreadId()

1
GetHashCode mutlaka benzersiz değildir! ve bunu bir iş parçacığını tanımlamak için kullanmamalıdır.
Dror Helper

2
OS iş parçacığı kimliğini istiyorsanız AppDomain.GetCurrentThreadId () kullanabilirsiniz, ancak birden çok .NET iş parçacığı teorik olarak aynı OS iş parçacığını paylaşabilir. Thread.GetHashCode () öğesinin, işlem boyunca benzersiz olan ve muhtemelen istediğiniz bir değer döndüreceği garanti edilir.
Mark Byers

3
Yöntem, kullanımdan kaldırıldı ve iyi bir sebeple işaretlendi. Daha dolgun resim için lütfen cevabım ve yapılandırıcıma bakın.
Paul Turner

3
OS Konu Kimliğine ulaşmanın tek yolu budur. Ve bu doğru cevap olarak işaretlenmelidir. Buna rağmen artık buna güvenmeyeceğim.
LolaRun

1
AppDomain.GetCurrentThreadId()eski: AppDomain.GetCurrentThreadId yönetilen iş parçacıkları çalışırken sabit bir kimlik sağlamadığı için kullanımdan kaldırıldı fibers (aka lightweight threads). Yönetilen bir iş parçacığının kararlı bir tanımlayıcısını almak için açık ManagedThreadIdözelliğini kullanın Thread. Kullanım:Thread.CurrentThread.ManagedThreadId
Lijo Joseph

22

MSDN'ye göre :

Yönetilmeyen bir ana bilgisayar yönetilen ve yönetilmeyen iş parçacıkları arasındaki ilişkiyi denetleyebildiğinden, bir işletim sistemi ThreadId'nin yönetilen iş parçacığıyla sabit bir ilişkisi yoktur. Özellikle, gelişmiş bir ana bilgisayar, birçok yönetilen iş parçacığını aynı işletim sistemi iş parçacığına karşı zamanlamak veya yönetilen bir iş parçacığını farklı işletim sistemi iş parçacıkları arasında taşımak için CLR Barındırma API'sını kullanabilir.

Yani, temel olarak, Threadnesne mutlaka bir OS iş parçacığına karşılık gelmez - bu yüzden yerel kimliğe maruz kalmaz.


VS2010'daki Hata Ayıklama / Konu penceresi "Yönetilen iş parçacığı kimliği" ni gösterir. Bunu nasıl alabilirim?
Pavel Radzivilovsky

1
ManagedThreadID özelliği kullanın msdn.microsoft.com/en-us/library/... . Bu, OS iş parçacığı kimliğiyle aynı değildir.
yapılandırıcı

15

Saldırmak üzere olanlar için:

    public static int GetNativeThreadId(Thread thread)
    {
        var f = typeof(Thread).GetField("DONT_USE_InternalThread",
            BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);

        var pInternalThread = (IntPtr)f.GetValue(thread);
        var nativeId = Marshal.ReadInt32(pInternalThread, (IntPtr.Size == 8) ? 548 : 348); // found by analyzing the memory
        return nativeId;
    }

11

Geçerli iş parçacığı kimliğini bulmak için - `` Thread.CurrentThread.ManagedThreadId '' kullanın. Ancak bu durumda geçerli win32 iş parçacığı kimliğine ihtiyacınız olabilir - bu işlevle almak için pInvoke kullanın:

[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
public static extern Int32 GetCurrentWin32ThreadId();

Öncelikle yönetilen iş parçacığı kimliğini ve win32 iş parçacığı kimliği bağlantısını kaydetmeniz gerekir - win32 kimliğini yönetilen iş parçacığına eşleyen bir sözlük kullanın.

Sonra id tarafından bir iş parçacığını bulmak için Process.GetCurrentProcess () kullanarak işlemin iş parçacığı üzerinde yinelenen. Konuları ve bu kimliğe sahip iş parçacığını bulmak için:

foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
{
     var managedThread = win32ToManagedThread[thread.id];
     if((managedThread.ManagedThreadId == threadId)
     {
         return managedThread;
     }
}

OP yönetilen iş parçacığı kimliğiyle aynı değildir iş parçacığının OS kimliği istiyor inanıyorum.
Brian Rasmussen

Bu kod çalışmaz: Process.Threads bir ProcessThreadnesne koleksiyonu döndürür , bu aynı değildir (veya devralmaz) Thread: (thread as Thread)boş bir başvuru döndürür.
Fredrik Mörk

Kod kodu birkaç hata olduğunu fark ettim - şimdi denedim düzeltildi
Dror Helper

1
Bir win32 id yönetilen bir iş parçacığı ile eşleyen bir sözlük kullanarak sona erdi.
Contango

11

Windows 10 altındaki ofset 0x022C (x64-bit-Uygulama) ve 0x0160 (x32-bit-Uygulama):

public static int GetNativeThreadId(Thread thread)
{
    var f = typeof(Thread).GetField("DONT_USE_InternalThread",
        BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);

    var pInternalThread = (IntPtr)f.GetValue(thread);
    var nativeId = Marshal.ReadInt32(pInternalThread, (IntPtr.Size == 8) ? 0x022C : 0x0160); // found by analyzing the memory
    return nativeId;
}

1
SP1 ile Windows 7 x64 üzerinde de çalışır. Gerçi tavsiye edilmez. Sadece geçici testlerde kullanın.
guan boshen

5

System.Threading.Thread.CurrentThread.Name

System.Threading.Thread.CurrentThread.ManagedThreadId

5

Yönetilen koddan, Threadyönetilen her iş parçacığı için türün örneklerine erişebilirsiniz .Threadbir OS iş parçacığı kavramını kapsar ve mevcut CLR'den yönetilen iş parçacıkları ve OS iş parçacıkları ile bire bir uyum vardır. Ancak bu, gelecekte değişebilecek bir uygulama detayıdır.

Visual Studio tarafından görüntülenen kimlik aslında OS iş parçacığı kimliğidir. Bu değil birkaç yanıt tarafından önerilen yönetilen iş parçacığı kimliğiyle aynı .

ThreadTipi denilen özel ıntptr üyesi alanını içermez DONT_USE_InternalThreadhangi noktaları altta yatan OS yapısına,. Bununla birlikte, bu gerçekten bir uygulama detayı olduğundan, bu IMO'yu takip etmek önerilmez. Ve adı bir çeşit buna güvenmemeniz gerektiğini gösterir.


GetThreadId'i kullanmak için DONT_USE alanından alacağınız tanıtıcıya ihtiyacınız olacaktır.
konfigüratör

Biliyorum, ama dediğim gibi gerçekten yönetilen iş parçacığı doğrudan OS iş parçacıkları eşler güvenemezsiniz, bu yüzden ben güvenmezdim.
Brian Rasmussen

Açıklığa kavuştuğunuz ve sorunu özetlediğiniz için çok teşekkürler. Ancak şimdi birden çok yönetilen iş parçacığı tek bir OS iş parçacığına karşılık gelebiliyorsa (yapılandırıcının belirttiği gibi - ve teşekkür etti), bu VS'nin Yönetilen İş Parçasını değil OS iş parçacıklarını gösterdiği anlamına gelir.
LolaRun

@OhrmaZd: Evet, VS2005 / 2008, Konular penceresinde yönetilen iş parçacıkları için işletim sistemi kimliklerini gösterir. VS2010B2 aslında iş parçacığı başına hem işletim sistemini hem de yönetilen kimliği gösterir.
Brian Rasmussen

@Brian Rasmussen: Şimdi yönetilen bir konu için bir kimlik! Bilgilerinizi paylaştığınız için teşekkür ederiz.
LolaRun

4

Yönetilen iş parçacığı kimliğini döndüren Thread.GetHashCode öğesini kullanabilirsiniz. GetHashCode'un amacını düşünüyorsanız, bu mantıklıdır - nesne (iş parçacığı) için benzersiz bir tanımlayıcı (örn. Sözlükte bir anahtar) olması gerekir.

Konu sınıf için referans kaynağı burada öğreticidir. (Verilen belirli bir .NET uygulaması olabilir bu kaynak koduna ama şansımı alacağım hata ayıklama amacıyla dayalı edilemez.)

GetHashCode , "nesne eşitliğinin hızlı bir şekilde kontrol edilmesini gerektiren algoritmalar için bu karma kodu sağlar," bu nedenle, Konu eşitliğini kontrol etmek için çok uygundur - örneğin, çağrılmasını istediğiniz iş parçacığında belirli bir yöntemin yürütüldüğünü iddia etmek.


4
Harika, bu 5 yaşındaki soruyu bir saatliğine açık tuttum, geri döndüm ve "Bu soruya 1 yeni cevap" gördüm: D
Ray

Bu cevap başka bir yorumda ima edildi, ancak daha fazla araştırma yaptıktan sonra kullandım. Muhtemelen OP'nin istediği şey değil. Muhtemelen OP artık umursamıyor. Başka biri için yararlı olabilir. (Ve en azından referans kaynağına dayanarak, iş parçacığı kimliğini almanın en etkili yolu bu olabilir.)
yoyo

iyi şu anda farklı bir alandayım, ama o zamanlar, bir iş parçacığı için iki kimlik, yerel iş parçacığının kimliği ve yönetilen iş parçacığı için bir kimlik vardı ve biri diğerine ait ... Kimlikler iş parçacıklarını tanımlamak için tasarlanmıştır, GetHashCodes başka bir yardımcı program vardır ve çarpışabilir. GetHashCode
LolaRun'u

3
@yoyo Çarpışmalar sözlük kullanımını bozmaz. Çarpışma olasılığı düşük, hiç çarpışma olmayacak şekilde tasarlanmıştır. 128bit değerine 64bit değerine sahipseniz, her karma değerinde yaklaşık 2 ^ 64 çarpışma olur. Sözlük, nadiren bir çarpışma meydana geldiğinde bir geri dönüş algoritmasına sahip olacak şekilde tasarlanmıştır .
bradgonesurfing

2
@bradgonesurfing Kesinlikle haklısın ve önceki yorumum yanlış. Sözlük performansı karma çarpışmalarla bozulur, ancak işlevsellik doğru kalır. Yanıltıcı yorum için özür dilerim, bunu işaret ettiğiniz için teşekkürler.
yoyo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.