2012-09-08 23 views
7

(viết bài này với câu trả lời vì tôi không thể tìm thấy một lời giải thích đầy đủ về cách làm bất cứ nơi nào này, vì vậy tôi nghĩ rằng nó có thể có một số giá trị cho một người nào đó)Set xử lý chủ đề mối quan hệ trong Microsoft Net

Làm thế nào tôi có thể đặt ái lực bộ vi xử lý của một chuỗi cụ thể trong Microsoft .Net? Đặt mối quan hệ của quy trình là tầm thường thông qua System.Diagnostics.Process.ProcessorAffinity, nhưng lớp System.Threading.Thread không cung cấp chức năng như vậy và .Net không đảm bảo chuỗi được quản lý được liên kết với bất kỳ chuỗi hệ điều hành cụ thể nào.

Trả lời

25

Sự tách biệt giữa các chuỗi hệ thống được quản lý và vận hành có ngày trở lại .Net 2.0 và kế hoạch của nhóm SQL Server để triển khai các luồng Net sử dụng các sợi. Điều này không bao giờ thực sự đi đâu cả, vì vậy trong khi không có gì đảm bảo rằng một luồng được quản lý sẽ luôn chạy trên cùng một luồng hệ điều hành, trong thực tế, đây luôn là trường hợp cho tất cả các máy chủ .Net hiện tại. Cho rằng điều này đã không thay đổi trong tất cả các năm kể từ khi giới thiệu .Net 2.0, nó không chắc điều này sẽ bao giờ thay đổi.

Có thể tăng cường sự tự tin của chúng tôi ngay cả đối với các phiên bản tương lai của. Net bằng cách sử dụng phương thức System.Threading.Thread.BeginThreadAffinity. Điều này đảm bảo rằng luồng được quản lý sẽ nằm trên cùng một luồng hệ điều hành (vì vậy nó không có gì trên máy chủ CLR mặc định, vì nó đã đúng theo mặc định). Tôi cho rằng nó vẫn có thể là các luồng quản lý khác có thể chia sẻ cùng một luồng hệ điều hành, nhưng điều này dường như không chắc chắn và chắc chắn không phải là trường hợp trong bất kỳ máy chủ .Net hiện tại nào.

.Net cung cấp khả năng truy cập các chuỗi hệ điều hành gốc sử dụng lớp System.Diagnostics.ProcessThread và lớp này có khả năng thay đổi ái lực bộ xử lý của chuỗi bằng cách sử dụng thuộc tính ProcessorAffinity. Tuy nhiên, việc liên kết một chuỗi được quản lý cụ thể với số ProcessThread của chúng tôi đã được thực hiện một cách có chủ ý.

Cách thực sự duy nhất để thực hiện điều đó là từ bên trong chính chuỗi đó. Sử dụng phương thức System.AppDomain.GetCurrentThreadId (hoặc PInvoke chức năng GetCurrentThreadId nếu bạn không muốn gọi phương thức không dùng nữa, mặc dù điều đó sẽ không hoạt động với Mono trên các hệ điều hành khác ngoài Windows). Điều này sau đó có thể được kết hợp với thuộc tính ProcessThread.Id.

này làm cho nó có thể thiết lập mối quan hệ bộ vi xử lý của chủ đề với đoạn mã sau (được gọi từ bên thread):

/// <summary> 
/// Sets the processor affinity of the current thread. 
/// </summary> 
/// <param name="cpus">A list of CPU numbers. The values should be 
/// between 0 and <see cref="Environment.ProcessorCount"/>.</param> 
public static void SetThreadProcessorAffinity(params int[] cpus) 
{ 
    if(cpus == null) 
     throw new ArgumentNullException("cpus"); 
    if(cpus.Length == 0) 
     throw new ArgumentException("You must specify at least one CPU.", "cpus"); 

    // Supports up to 64 processors 
    long cpuMask = 0; 
    foreach(int cpu in cpus) 
    { 
     if(cpu < 0 || cpu >= Environment.ProcessorCount) 
      throw new ArgumentException("Invalid CPU number."); 

     cpuMask |= 1L << cpu; 
    } 

    // Ensure managed thread is linked to OS thread; does nothing on default host in current .Net versions 
    Thread.BeginThreadAffinity(); 

#pragma warning disable 618 
    // The call to BeginThreadAffinity guarantees stable results for GetCurrentThreadId, 
    // so we ignore the obsolete warning 
    int osThreadId = AppDomain.GetCurrentThreadId(); 
#pragma warning restore 618 

    // Find the ProcessThread for this thread. 
    ProcessThread thread = Process.GetCurrentProcess().Threads.Cast<ProcessThread>() 
           .Where(t => t.Id == osThreadId).Single(); 
    // Set the thread's processor affinity 
    thread.ProcessorAffinity = new IntPtr(cpuMask); 
} 

Hãy ghi nhớ rằng trong khi làm việc này trên các phiên bản hiện tại của Net, về mặt lý thuyết việc thiếu bảo đảm rằng các luồng được quản lý bị ràng buộc với các luồng hệ điều hành có thể phá vỡ mã này trong tương lai. Tuy nhiên, tôi cho rằng điều này rất khó xảy ra.

Các vấn đề liên quan