2010-02-10 107 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