动态执行方法

时间:2010-02-10 11:13:22

标签: c#

我很多次使用这样的代码:

public static void ExecuteMethod1InThread(string msg)
{
    Thread t = new Thread(
        new ThreadStart(
            delegate
            {
                log(msg);
            }));
    t.IsBackground = true;
    t.Start();
    t.Join();
}

如果你注意到我在一个单独的线程中调用一个方法,希望它对性能有帮助。

但是我想知道是否可以动态地给出方法名称和参数并让它执行它而不是为每个方法调用创建如上所述的代码块。

我知道我们可以使用反射,但它会影响性能是我的理解。

我也听说过匿名代表,但我不确定他们是如何工作的。 只是想知道是否有人可以启发。

5 个答案:

答案 0 :(得分:7)

(请阅读底部的关键点!)

好吧,你已经在使用匿名方法了。您可以继续使用C#2.0并使代码更短一些:

public static void ExecuteMethod1InThread(string msg)
{
    Thread t = new Thread(delegate() { log(msg); });
    t.IsBackground = true;
    t.Start();
    t.Join();
}

或者您可以使用C#3中的lambda表达式:

public static void ExecuteMethod1InThread(string msg)
{
    Thread t = new Thread(() => log(msg));
    t.IsBackground = true;
    t.Start();
    t.Join();
}

现在你可以更简单地调用这样的不同方法:

public static void ExecuteMethodInThread<T>(Action<T> method, T argument)
{
    Thread t = new Thread(() => method(argument));
    t.IsBackground = true;
    t.Start();
    t.Join();
}

然后用“

”来调用它
ExecuteMethodInThread(Log, "message");
ExecuteMethodInThread(DifferentMethod, 10);

(例如)。

或者,您可以将其更改为仅以ThreadStart开头:

public static void ExecuteMethodInThread(ThreadStart action)
{
    Thread t = new Thread(action);
    t.IsBackground = true;
    t.Start();
    t.Join();
}

并将其称为:

ExecuteMethodInThread(() => Log("Message"));
ExecuteMethodInThread(() => DoSomethingElse(20));

这不是完全等效,但是,由于评估了各种表达式。特别是,在循环中执行此操作可能会导致问题Eric Lippert describes here

重点

但是,您目前获得的将伤害表现。你正在开始一个新线程(而不是使用线程池)然后你正在等待线程完成。这是有效地同步调用log方法 - 这有助于提高性能吗?

答案 1 :(得分:4)

线程通常用于同时执行多项操作。

例如,您可能希望下载网页,分析其内容并使用其中的某些值。同时,在下载页面时,您可能希望从数据库加载一些数据,以与网页中的值一起使用。

所以你可以这样做:

------+------ read from database ----------------+--- process data   Thread #1
       \                                        /
        \                                      /
         +--- download and analyze webpage ---+                      Thread #2

但是,在您的情况下,您执行此操作:

------+                                          +--- process data   Thread #1
       \                                        /
        \                                      /
         +--- log(msg) -----------------------+                      Thread #2

这没有任何意义,只会增加代码的开销。

我只想将你的例子重写为:

public static void ExecuteMethod1InThread(string msg)
{
    log(msg);
}

净效果将是相同的。

答案 2 :(得分:2)

实际上,由于t.Join(),上面的代码无助于提高性能。此方法的本质是等待线程完成。因此,您的主线程将等待,并且不会发生并行性。

答案 3 :(得分:0)

除非委托中的工作相当复杂,否则生成一个新线程可能比在手头的线程上完成工作需要更多的时间。

对于短期运行任务,您通常应该更喜欢ThreadPool。它有各种调度作业的选项。它并不总是最合适的,但是由于它为短期运行任务分摊产生新线程的成本,它将比为每个新任务生成一个线程更有效。

答案 4 :(得分:0)

在新线程中弹出一个消息框不是最聪明的事情,但是,仅举一个例子,

WaitCallback cb = new WaitCallback(state =>
{
    MessageBox.Show(state.ToString());
});

private void SomeMethod()
{
    ThreadPool.QueueUserWorkItem(cb, "test");
}

编辑:

WaitCallback logger = new WaitCallback(msg =>
{
    log(msg.ToString());
});

public static void ExecuteMethod1InThread(string msg)
{
    ThreadPool.QueueUserWorkItem(logger, msg);
}