【问题标题】:Generic ThreadPool in .NET.NET 中的通用线程池
【发布时间】:2012-11-02 15:37:31
【问题描述】:

这对我来说是一个相对常见的任务,我认为对于许多 .NET 程序员来说也是如此:
我想使用 .NET ThreadPool 来调度需要处理给定类型任务的工作线程。

作为复习,ThreadPool 的队列方法及其关联委托的签名是:

public static bool QueueUserWorkItem (
    WaitCallback callBack,
    Object state
)
public delegate void WaitCallback (Object state)

因此,典型的通用工作线程类看起来像:

public class Worker<T> {
    public void schedule(T i_task) {
        ThreadPool.QueueUserWorkItem(execute, i_task)
    }
    private void execute(Object o){
        T task = (T)o;  //What happened to the type safety?  
        executeTask(task);
    }
    private void executeTask(T i_task){
        //process i_task
    }
}

注意到state 参数的类型了吗?这是Object

.NET 团队选择不使QueueUserWorkItem 方法(或整个ThreadPool 类)通用的令人信服的原因是什么?我不敢相信他们只是忽略了它。

这是我希望看到的:

//in the ThreadPool class:
public static bool QueueUserWorkItem<T> (
    WaitCallback<T> callBack,
    T state
)
public delegate void WaitCallback<T> (T state)

这将使工人类类型安全(并且更清晰,恕我直言):

public class Worker<T> {
    public void schedule(T i_task) {
        ThreadPool.QueueUserWorkItem<T>(execute, i_task)
    }
    private void execute(T i_task){
        //process i_task
    }
}

我一定是错过了什么。

【问题讨论】:

    标签: c# .net multithreading generics threadpool


    【解决方案1】:

    由于通过将匿名委托或 lambda 传递给线程池(通过变量捕获)来打包您喜欢的任何状态都很简单,因此不需要通用版本。

    例如,您可以编写一个实用函数:

    static void QueueItem<T>(Action<T> action, T state)
    {
        ThreadPool.QueueUserWorkItem(delegate { action(state); });
    }
    

    但这不会非常有用,因为您可以在需要池任务中的状态的任何时候自己使用委托。

    【讨论】:

      【解决方案2】:

      听起来您在谈论工作队列? (而且我听起来很笨拙……)

      为了记录,线程池线程通常应该用于短的工作。理想情况下,您应该为长寿命队列创建自己的线程。请注意,.NET 4.0 可能正在采用 CCR/TPL 库,因此我们将免费获得一些内置的工作队列——但编写线程工作队列并不难。你也可以让它通用;-p

      这个问题 - 我更喜欢使用捕获的变量方法将状态传递给线程(无论是 ThreadThreadPool 还是 Control.Invoke):

          Thread t = new Thread(() => SomeMethod(arg));
          t.IsBackground = true;
          t.Name = "Worker n";
          t.Start();
      

      这使您可以更精细地控制线程,而不会使ThreadPool 饱和。

      【讨论】:

      • 我不明白您关于不使用线程池作为工作队列的底层“执行”层的论点。由于那里的线程数量有限,在使用 .NET ThreadPool 类时这是一个问题吗? IMO 很自然地假设工作队列中的任务很短。能详细点吗?
      【解决方案3】:

      ThreadPool 自 .NET 1.1 以来就存在,它没有泛型。

      我喜欢他们选择不破坏向后兼容性的方式:-)

      【讨论】:

      • 我不认为这是一个有效的论点。只需查看 1.1 中所有在 2.0 中“升级”为使用泛型的容器类。另外,我并不是建议将 Queue... 方法替换为它的通用对应方法,而是在其旁边添加通用版本。
      猜你喜欢
      • 1970-01-01
      • 2011-04-08
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      • 2011-02-27
      • 1970-01-01
      • 1970-01-01
      • 2013-11-07
      相关资源
      最近更新 更多