Mỗi thread trong .NET có một Managed Thread ID duy nhất (integer) do CLR gán. Dùng Thread.CurrentThread.ManagedThreadId để lấy ID của thread đang chạy.
Ví dụ cơ bản
using System;
using System.Threading;
class Program
{
static void Main()
{
Thread mainThread = Thread.CurrentThread;
mainThread.Name = "Main Thread";
Console.WriteLine($"Thread Name: {Thread.CurrentThread.Name}");
Console.WriteLine($"Managed Thread ID: {Thread.CurrentThread.ManagedThreadId}");
// Output: Managed Thread ID: 1 (thường là 1 cho main thread)
// Tạo thread mới
Thread worker = new Thread(DoWork);
worker.Name = "Worker Thread";
worker.Start();
Console.ReadLine();
}
static void DoWork()
{
Console.WriteLine($"Worker - Name: {Thread.CurrentThread.Name}");
Console.WriteLine($"Worker - Managed Thread ID: {Thread.CurrentThread.ManagedThreadId}");
// Output: Worker - Managed Thread ID: 3, 4, 5... (tùy ThreadPool)
}
}
Thread ID vs OS Thread ID
- ManagedThreadId: ID do CLR quản lý, duy nhất trong process .NET, bắt đầu từ 1.
- OS Thread ID: ID do OS cấp (GetCurrentThreadId Windows, pthread_self Linux). Khác ManagedThreadId.
- Lấy OS Thread ID:
System.Diagnostics.Process.GetCurrentProcess().Threadshoặc P/InvokeGetCurrentThreadId().
Task vs Thread
// Task chạy trên ThreadPool thread
Task.Run(() =>
{
Console.WriteLine($"Task - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
// Thread ID có thể khác nhau mỗi lần chạy (ThreadPool reuse)
}).Wait();
// LongRunning Task -> có thể tạo thread mới
Task.Factory.StartNew(() =>
{
Console.WriteLine($"LongRunning - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
}, TaskCreationOptions.LongRunning);
Async/Await và Thread ID
static async Task Main()
{
Console.WriteLine($"Start - Thread: {Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(100);
Console.WriteLine($"After await - Thread: {Thread.CurrentThread.ManagedThreadId}");
// Có thể KHÁC thread nếu không có SynchronizationContext (Console App)
// Cùng thread nếu có SyncContext (UI: WPF, WinForms, ASP.NET Core request)
}
Ứng dụng thực tế
- Debugging: Log Thread ID để trace concurrency issues.
- Thread-local storage:
ThreadLocal<T>keyed by Thread ID. - Performance profiling: Xem thread contention.
- Đảm bảo code chạy trên UI thread (WPF/WinForms):
Dispatcher.Invoke/Control.Invoke.
Lưu ý
- Managed Thread ID có thể bị tái sử dụng (recycled) sau khi thread kết thúc.
- Không dùng Thread ID làm unique key lâu dài (dùng
Thread.CurrentThread.ManagedThreadIdchỉ cho debug/logging tức thời). - Trong ASP.NET Core, không nên phụ thuộc vào Thread ID (thread pool, async context switching).