泛化.NET后台工作者

时间:2009-04-06 17:53:50

标签: .net winforms multithreading reflection backgroundworker

我们正在开发一个Windows应用程序,它定期启动可能需要一些时间的操作。我们已经进入了一种模式,即在BackgroundWorker上运行这些操作,并为每个操作编写一个快速的WinForm,在这里您将表单传递给必要的参数,表单连接BackgroundWorker并进行函数调用,以及表单显示输出(进度条移动,文本填满更新等)。

现在很明显,这种形式非常棒。表单副本之间唯一真正不同的部分是在哪个对象上调用哪个方法。所以我们喜欢做的是使它成为通用的,我们可以采用表单,传入一个对象(或静态调用的null?),一个函数名和一个参数数组,让它只是“去”从那里。我们已经能够用Reflection做到这一点。在这种情况下,我们不喜欢反思的是缺乏强烈的打字;错误拼写方法调用之类的东西会在运行时捕获,而不是编译时。现在有什么可以使它更优雅和健壮吗?我听说有人谈论代表和表达树等事情;但我不确定前者是否适用,对后者仍然有点暗淡。

3 个答案:

答案 0 :(得分:6)

制作一个通用表单并传递一个指向它应该在BackgroundWorker上运行的方法的委托,这将是一个明智的解决方案。

您可以让Form构造函数将泛型委托(Action可能是一个好主意)作为参数,并在构造函数中传递一个与Action的签名匹配的lambda表达式。然后,foreach动作,你只需要指定适当的lambda表达式。

请记住,lambda表达式可以捕获局部变量,因此您可以调用之前执行的任何逻辑并传递相同的参数。

答案 1 :(得分:3)

您可能还想查看Lambda函数。我在使用Generics时特别使用它们。否则,代表们可能会正常工作。

答案 2 :(得分:2)

你可以做的一件事是创建几个不同的方法(一个用于没有参数的方法,一个用于带有一个参数的方法,等等),如下所示:

public static void DisplayForm(Action action) {
    DisplayFormUsingInvoke(action);
}

public static void DisplayForm<T>(Action<T> action, T param) {
    DisplayFormUsingInvoke(action, param);
}

public static void DisplayForm<T,U>(Action<T,U> action, T param1, U param2) {
    DisplayFormUsingInvoke(action, param1, param2);
}

...

然后,您可以拥有一个实际工作的私有方法,与您当前的方法类似,但不会暴露给客户端代码:

private static void DisplayFormUsingInvoke(Delegate d, params object[] parms) {
    // Edit this code to run it on the background thread, report progress, etc.
    d.DynamicInvoke(parms);
}

然后客户端代码将调用其中一个公共方法,这些方法将强制要求提供正确数量和类型的参数。