2010-02-10 68 views
1

很多时候,我用这样的代码:执行的方法动态

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

如果你注意到我打电话的方法在一个单独的线程希望它会在性能很有帮助。

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

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

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

+2

这是性能比使用配发更糟反射。创建一个线程来调用一个方法是一个不错的选择。你应该使用线程池。 – 2010-02-10 11:15:55

回答

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(); 
} 

,并调用它像这样:

​​

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

重要的一点

然而,目前你有什么会伤害性能。你开始一个新的线程(而不是使用线程池),然后你等待线程完成。这是有效同步调用log方法 - 如何可以帮助性能?

+0

不要忘记创建一个新线程是一个非常昂贵的操作(系统将立即分配1MB的内存)。正如Jon所说:使用线程池。 – Steven 2010-02-10 11:28:57

0

除非委托中的工作相当详细,否则产生一个新线程可能需要更多的时间,而不仅仅是对正在执行的线程进行工作。

对于短时间运行的任务,您通常应该更喜欢ThreadPool。它有调度工作的各种选项。它并不总是最合适的,但是当它分摊产生短线程任务的新线程的成本时,它比为每个新任务产生线程要高效得多。

2

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

+0

好的。我甚至没有注意到这一点。 – 2010-02-10 11:18:59

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); 
} 

的净效应将是相同的。

+0

好的回到未来的东西,你有... – Kobi 2010-02-10 11:25:16

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); 
} 
+0

Sorin你可以重新写这个使用上面的代码片段,我给了。 谢谢 – 2010-02-10 11:59:21

+0

编辑以匹配原始代码段。 – 2010-02-10 12:42:50