【问题标题】:Why .Net has no generic version of Thread.Start()?为什么 .Net 没有通用版本的 Thread.Start()?
【发布时间】:2013-01-31 22:35:11
【问题描述】:

我想知道为什么 .Net 没有用于启动线程的通用方法。

例如我们像下面这样启动一个线程......

Thread th = new Thread(SayHello);
th.Start("Hello");

private static void SayHello(object obj)
        {
            string str = obj as string;
            Console.WriteLine(str);
        }

为什么我们不能拥有我的意思是为什么 .Net 团队不考虑使其通用?

类似跟随...

Thread<string> th = new Thread<string>(SayHello);

因为很多时候当我将值类型传递给线程启动时,我必须进行装箱/拆箱。

【问题讨论】:

  • 您可以轻松地自己添加这样的包装类。 (另外,这个特定的例子不是装箱/拆箱,只是参考向下转换。)
  • 出于兴趣,与启动新线程或线程间上下文切换的成本相比,您认为装箱/拆箱对性能的影响有多大?

标签: c# multithreading


【解决方案1】:

我可以看到实现 BCL 的人不费心写这样的东西的几个原因:

  1. 如果您担心性能,那么与实际创建线程相比,演员表(即使是拆箱)的影响要小得多。
  2. 如果您担心类型安全,可以轻松使用 lambda:new Thread(() =&gt; SayHello("Hello"))
  3. Thread&lt;T&gt; 将是一个令人困惑的类型,因为尚不清楚 T 代表什么。特别是因为它与Task&lt;T&gt; 中的T 具有完全不同的含义。
  4. 如果需要,您可以使用 20 行将 Thread&lt;T&gt; 创建为包装器(见下文)。

因此,如果它确实困扰您并且解决方案可能会令人困惑,那么问题很小并且很容易解决。这很可能是为什么没有花费资源来实现它的原因。


Thread&lt;T&gt;的可能实现:

class Thread<T>
{
    private readonly Action<T> m_action;
    private readonly Thread m_thread;
    private T m_parameter;

    public Thread(Action<T> action)
    {
        m_action = action;
        m_thread = new Thread(DoWork);
    }

    public void Start(T parameter)
    {
        m_parameter = parameter;
        m_thread.Start();
    }

    private void DoWork()
    {
        m_action(m_parameter);
    }
}

【讨论】:

    【解决方案2】:

    因为还没有人写过那个方法。此外,由于这里的装箱/拆箱只是整个操作的一小部分并且实际上很少有程序员需要手动启动线程(大多数用例都有更好的抽象) ,他们可能认为几乎不需要指定、实施、测试和记录本质上不需要的更改。

    【讨论】:

      【解决方案3】:

      使用 lambda 启动线程以使用强类型非常容易,因此他们不需要为其添加任何新的语言支持。

      例如:

      using System;
      using System.Threading;
      
      class Program
      {
          static void Main(string[] args)
          {
              // Easy way to start a thread with strongly-typed multiple parameters:
      
              new Thread(() => MyThreadFunc("Test", 42, DateTime.Now)).Start();
      
              Console.WriteLine("Started thread.");
              Thread.Sleep(2000);
          }
      
          static void MyThreadFunc(string param1, int param2, DateTime param3)
          {
              Thread.Sleep(1000);
              Console.WriteLine("param1 = {0}, param2 = {1}, param3 = {2}", param1, param2, param3);
          }
      }
      

      【讨论】:

        【解决方案4】:

        .net 中有很多类,如果它们是在引入泛型之后设计的,我猜它们会有一个泛型版本。线程只是其中之一。

        对于这个具体问题,如果可以使用.net 4.0+:

        使用 System.Threading.Tasks 命名空间中的 Task 类。

        private static void SayHello(string s)
        {
            Task t = new Task(() => Console.WriteLine(s));
            t.Start();
        }
        

        这个例子是类型安全的,并且和你的例子一样。方法不同,如果您期待结果,Task 确实更有意义,但它仍然是一个很好的替代品,我认为即使在这里。我的猜测是 MS 不会将工作放在“旧”线程类中,但可能会继续改进 Task Parallel Library

        【讨论】:

        • 虽然我通常同意使用Task 而不是Thread,但它并不能解决这个特定问题。
        • 您能否解释一下在这种情况下您将如何使用Task?因为我真的不认为它在这里会有所帮助。
        • Task 类不是线程的替代品。任务应该是短暂的,而不是持续的操作。你应该提到这一点。
        • @JustAnotherUserYouMayKnow 这就是 TaskCreationOptions.LongRunning 的用途。
        • 在您的新示例中,您可以将Task 替换为Thread,它仍然可以工作。这是使用 lambdas 的原因,但不是使用 Task 的原因。 Task 优于 Thread 的原因有很多,但这不是一个。
        【解决方案5】:

        由于“历史原因”。该方法是在 .NET 1(无泛型)中创建的,之后没有修复。和ICloneable等一样

        【讨论】:

        • 但是 Task 是在 .Net 4.0 中创建的,使用泛型和 still has this issue
        • 是的,但现在只使用 lambda 很容易,因此实现任意数量的类型参数并没有真正的好处 - 它们使用起来很讨厌,而且代码看起来很糟糕。跨度>
        【解决方案6】:

        奇怪.. 实际上没有人问为什么有人想做 OP 要求的事情。线程旨在运行一段代码。线程不是方法。从 .NET 中泛型的性质来看,代码 new Thread() 将意味着创建具有特定类型的对象 - 字符串。无论如何,这与 Thread 类运行一段时间并做一些事情的目的无关。复杂的东西。

        为了说明我的想法——这就像他问的一样——为什么我们不拥有配备电视机和 XBOX 的压路机......

        所以总而言之我的答案 - 这没有实现,因为它与 .NET 的体系结构相矛盾。即*错误*而不是因为他们没有打扰。

        【讨论】:

        • 我真的不明白你在说什么。线程运行一段代码,那段代码是一个方法。该方法可以接受输入,但必须是object,但不能将其限制为某种特定类型。
        • 另外,从泛型的性质来看,new Thread&lt;string&gt;() 意味着创建一个与string 有某种关系的对象,但它并没有说明它是哪种关系。为什么不能是“这是一个Thread,它运行一些将string 作为输入的代码”?
        猜你喜欢
        • 2015-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-11
        • 1970-01-01
        相关资源
        最近更新 更多