启动STA线程,但带有参数到最终功能

时间:2012-06-11 15:06:14

标签: c# delegates nunit

我对某些委托的行为方式有点弱,比如将方法作为要调用的参数传递。在尝试做一些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多个测试可以在这种模式下运行并且可能有未来具有不同参数计数和参数类型的其他类似测试。

感谢。

1 个答案:

答案 0 :(得分:2)

您可以使用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 Expressions (C# Programming Guide)了解更多信息。 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代理。