【问题标题】:c# thread declarationc#线程声明
【发布时间】:2012-12-14 00:46:50
【问题描述】:

我看到以下声明:

ThreadStart myThreadDelegate = new ThreadStart(Work.DoWork);
Thread myThread = new Thread(myThreadDelegate);
myThread.Start();

可以简化成下面这样吗?

Thread myThread = new Thread(new ThreadStart(Work.DoWork));
myThread.Start();

如果是,第二种方法叫什么?每种方法的优缺点是什么?

【问题讨论】:

  • 你怎么称呼这种较新的声明方法? =/
  • 您在两者中都在做同样的事情。它被称为 Instatiating 一个线程对象。在第一个示例中,您声明变量并为它们分配新对象。然后,您将这些传递给线程。您在第二个示例中执行完全相同的操作,而无需在变量中声明它们。唯一真正需要声明变量的是,如果您需要访问调用它的方法之外的线程。
  • '优化后重构代码'? '那整洁的单线'?

标签: c# multithreading delegates declaration


【解决方案1】:

两者都是一样的。

在第一个示例中,您拥有 myThreadDelegate,但它除了传递给 Thread constructor 之外没有其他用途。

【讨论】:

    【解决方案2】:

    好的, 有人提出这个建议,但随后删除了他/她的答案:

    Thread myThread = new Thread ( () => Work.Dowork() );
    

    那个东西叫做 lambda 表达式。

    【讨论】:

    • 但这与 OP 示例不同。它在之间添加了另一个方法调用int
    • 您必须拥有new Thread ( () => Work.Dowork() ) 才能使用。注意()DoWork 之后的方法调用。 lambda 表达式是一种匿名函数。它将为您创建一个行为类似于箭头的方法,并使用该生成的方法创建委托实例。
    • @Tilak 太好了,我没看到。被删除的评论也忘记了()。也许评论被删除是因为它的作者意识到当命名方法 (DoWork) 已经具有所需的签名和返回类型时不需要 lambda。
    • @JeppeStigNielsen:我是 Threading 新手,那么所需的签名和返回类型是什么?
    • @hoangnguyen 如果您查看the ThreadStart delegate type,您会发现它的参数为零(即采用零参数)。那是因为ThreadStart 后面的括号中没有任何内容。方法或委托的签名由参数列表(参数的顺序和类型)组成。其他东西,如refout 参数修饰符,或params 或可选参数也可以是签名的一部分。 返回类型在这里是void
    【解决方案3】:

    甚至可以简化为:

    var myThread = new Thread(Work.DoWork);
    myThread.Start();
    

    没有太大区别。在您的第一个示例中,委托实例有一个名称 myThreadDelegate,理论上可以稍后在方法中使用(可能用于其他用途)。

    如果一个人更喜欢其中包含多个级别的长表达式,或者更喜欢许多带有临时变量然后组合的小表达式,这主要是一个品味问题。

    在我看来,无论如何,使用方法组的隐式转换(如Work.DoWork)比编写new ThreadStart(Work.DoWork) 更简单。参见How to: Declare, Instantiate, and Use a Delegate (C# Programming Guide) 中的句子C# 2.0 提供了一种更简单的方式来编写前面的声明。这种更简单的方式正式称为方法组转换

    有关var 关键字的信息,请参阅Implicitly Typed Local Variables (C# Programming Guide)

    当然,您的示例中的最终单线将是:

    (new Thread(Work.DoWork)).Start();
    

    在这种情况下,您甚至不会获得对新线程(变量)的引用(实例方法Start() 返回void)。

    【讨论】:

    • 好吧,我相信 'var' 被称为隐式声明。
    • @hoangnguyen var 被称为隐式类型(本地)变量。由于赋值运算符= 右侧的类型为Thread,因此var 仅表示Thread。它仍然是Thread 类型的强类型变量。我更新了我的答案。
    【解决方案4】:

    是的,可以。

    如果委托仅用于作为对新 Thread() 方法的引用传递,那么可以通过这种方式优化该序列 - 减少一个对象声明。

    【讨论】:

    • 对象实际上是在这两种情况下创建的,它只是在第一种情况下被命名,而在第二种情况下是匿名的。唯一的“优化”是,首先,对象在离开作用域后才能被 GC,其次,它在使用后立即离开作用域,但即使是编译器也可能会为您优化并允许它成为较早收集,如果没有,则不会造成重大损失。
    • 我知道,你是对的@Servy - 我的意思是“优化”,就像人类可读性一样。
    【解决方案5】:

    当然可以简化为第二种方法。但是,如果在调试期间需要其他对象,它们将不可用。他们不太可能会这样做,但值得注意的是,构建更简洁的线条总是有这个缺点。

    【讨论】:

    • 我必须同意。我永远不想发现自己无法看到调试所需的微小细节。
    【解决方案6】:

    是的。它不被称为任何东西,没有优点或缺点。您可以使用额外的 C# 语法糖:

    Thread myThread = new Thread(Work.DoWork);
    myThread.Start();
    

    它会自动推断你要创建一个ThreadStart委托对象。

    【讨论】:

    • 嗯...我认为问题中的第二种方法称为匿名方法。如果我错了,请纠正我。
    • 不,匿名方法使用 delegate 关键字。除了“不使用局部变量”之外,它没有被称为任何有意义的东西。您不需要局部变量来传递方法参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-13
    • 2018-06-22
    相关资源
    最近更新 更多