启动 STA 线程,但带有最终函数的参数

本文关键字:函数 参数 STA 线程 启动 | 更新日期: 2023-09-27 18:36:44

我对某些委托的行为方式有点弱,例如将方法作为要调用的参数传递。 在尝试做一些 NUnit 测试脚本时,我需要运行许多测试。 这些测试中的每一个都需要创建一个 GUI,因此需要一个 STA 线程。 所以,我有类似的东西

public class MyTest
{
   // the Delegate "ThreadStart" is part of the System.Threading namespace and is defined as
   // public delegate void ThreadStart();
   protected void Start_STA_Thread(ThreadStart whichMethod)
   {
      Thread thread = new Thread(whichMethod);
      thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
      thread.Start();
      thread.Join();
   }
   [Test]
   public void Test101()
   { 
      // Since the thread issues an INVOKE of a method, I'm having it call the
      // corresponding "FromSTAThread" method, such as
      Start_STA_Thread( Test101FromSTAThread );
   }
   protected void Test101FromSTAThread()
   {
      MySTA_RequiredClass oTmp = new MySTA_RequiredClass();
      Assert.IsTrue( oTmp.DoSomething() );
   }
}

这部分工作正常... 现在是下一步。 我现在有一组不同的测试,它们也需要一个 STA 线程。 但是,我需要做的每件"事情"都需要两个参数......两个字符串(对于这种情况)。

我如何声明适当的委托,以便我可以一次性传入我需要调用的方法和两个字符串参数......在这种模式下,我可能有 20+ 个测试要运行,并且将来可能会有其他具有不同参数计数和参数类型的类似测试。

谢谢。

启动 STA 线程,但带有最终函数的参数

您可以使用 lambda 表达式。

下面是要在测试中调用的修改方法接受参数:

protected void Test101FromSTAThread(String arg1, Int32 arg2)
{
}

以下是使用 lambda 表达式调用Start_STA_Thread的方法:

public void Test101()
{
   Start_STA_Thread(() => Test101FromSTAThread("foobar", 123));
}

在这种情况下,lambda 表达式为:

() => Test101FromSTAThread("foobar", 123)

这与所需的ThreadStart委托匹配。两者都是没有参数的方法,具有 void 返回类型。

如果您不熟悉 lambda 表达式,可以通过阅读 MSDN 上的 Lambda 表达式(C# 编程指南)了解更多信息。lambda 表达式是一个匿名函数,在这里它创建一个委托。委托被传递给线程,当线程启动时,将执行匿名函数。在这种情况下,由于涉及线程,匿名函数将在您创建的线程上执行,而不是在测试运行程序线程上执行。

在 C# 中使用 lambda 表达式时,编译器将发出一个函数,其名称为"有趣",表示匿名函数。如果 lambda 表达式使用词法环境中的变量(例如,在 lambda 表达式之前定义的局部变量),编译器将在特殊类型(同样具有"有趣"名称)中生成匿名函数以创建所谓的闭包。这允许编译器将词法环境中的变量捕获到特殊类型的状态中,并在稍后执行匿名函数时使用它。在您的情况下,当线程启动时会发生这种情况。

上面的代码将生成类似这样的东西("有趣"的名称<Test101>b__0当然不会编译,但它在 IL 中完全有效):

public void Test101()
{
   Start_STA_Thread(<Test101>b__0);
}
// The "anonymous" function.
void <Test101>b__0()
{
   Test101FromSTAThread("foobar", 123);
}

请注意如何将<Test101>b__0用作ThreadStart委托。