1

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

谢谢。

4

1 回答 1

2

您可以使用 lambda 表达式。

这是您要在测试接受参数中调用的修改后的方法:

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

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

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委托。

于 2012-06-11T15:50:54.193 回答