2009-10-21 130 views
29

我有兩個函數,我想在不同的線程上運行(因爲它們是數據庫的東西,而不是立即需要)。在新線程上運行簡單函數的最佳方式?

的功能有:

  getTenantReciept_UnitTableAdapter1.Fill(rentalEaseDataSet1.GetTenantReciept_Unit); 
      getTenantReciept_TenantNameTableAdapter1.Fill(rentalEaseDataSet1.GetTenantReciept_TenantName); 

在JavaScript中,我知道我可以創建創建一個匿名函數和像這樣的東西很容易把它在一個新的線程:

setTimeout(new function(){doSomethingImportantInBackground();}, 500); 

有在C#中這樣的東西?

+2

就在旁邊,但Javascript代碼不會**在新線程上調用函數,它只是安排它在將來運行。 Javascript是單線程的,所以所有的代碼都運行在同一個線程上。 – 2016-02-28 00:44:33

回答

66

你的問題不是很清楚,恐怕。你可以輕鬆地開始一個新的線程與一些代碼,用在C#2匿名方法,和在C#3 lambda表達式:

匿名方法:

new Thread(delegate() { 
    getTenantReciept_UnitTableAdapter1.Fill(
     rentalEaseDataSet1.GetTenantReciept_Unit); 
}).Start(); 
new Thread(delegate() { 
    getTenantReciept_TenantNameTableAdapter1.Fill(
     rentalEaseDataSet1.GetTenantReciept_TenantName); 
}).Start(); 

Lambda表達式:

new Thread(() => 
    getTenantReciept_UnitTableAdapter1.Fill(
     rentalEaseDataSet1.GetTenantReciept_Unit) 
).Start(); 
new Thread(() => 
    getTenantReciept_TenantNameTableAdapter1.Fill(
     rentalEaseDataSet1.GetTenantReciept_TenantName) 
).Start(); 

你可以使用與Control.Invoke相同類型的語法,但它稍微複雜一些,因爲可以使用任何委託 - 因此您需要告訴編譯器您正在使用哪種類型,而不是依賴於隱式轉換。這可能比較容易寫:

EventHandler eh = delegate 
{ 
    // Code 
}; 
control.Invoke(eh); 

EventHandler eh = (sender, args) => 
{ 
    // Code 
}; 
control.Invoke(eh); 

作爲一個側面說明,是你的名字是那麼長?你能縮短它們以獲得更易讀的代碼嗎?

+0

我認爲OP希望每次調用Fill()以在其自己的線程上運行。但除此之外,發現。 – LBushkin 2009-10-21 20:10:53

+0

@Lushushkin:會調整。說實話,這不是一個非常明確的問題。 – 2009-10-21 20:13:40

+0

我打算擴大我的答案,包括拉姆達的,但你的是更完整(和更好)無論如何。背景工作組件仍然是一個選項,因爲您不必擔心Control.Invoke。 – RichardOD 2009-10-21 20:14:14

6

你可以使用匿名方法:


void Foo() 
{ 
    Thread myThread = new System.Threading.Thread(delegate(){ 
       //Your code here 
    }); 
    myThread.Start(); 
} 
+1

它給出錯誤跨線程操作無效:從其創建的線程以外的線程訪問控制。 – 2014-08-05 07:18:27

+0

@PrakashVishwakarma這是因爲您正在訪問窗體的Control元素,但是在與UI線程不同的線程上。你需要做textboxInput.Invoke(new MethodInvoker(()=> {Whatever();}));它會安排匿名函數()=> {Whatever(); }在UI線程上。 – 2016-10-31 20:16:25

10

啓動線程是比較昂貴的。

你可能會使用一個線程從線程池的更好:

ThreadPool.QueueUserWorkItem(unused => 
    getTenantReciept_UnitTableAdapter1.Fill(
     rentalEaseDataSet1.GetTenantReciept_Unit) 
); 
ThreadPool.QueueUserWorkItem(unused => 
    getTenantReciept_TenantNameTableAdapter1.Fill(
     rentalEaseDataSet1.GetTenantReciept_TenantName) 
); 
+0

您如何知道線程何時完成? 也就是說。我做了:'ThreadPool.QueueUserWorkItem(unused => data [0] = get_data(a,b));''ThreadPool.QueueUserWorkItem(unused => data [1] = get_data(a2,b2));' – 2016-09-29 15:27:53

+1

這是2016現在。 'ThreadPool.QueueUserWorkItem'是2009年。使用任務(請參閱@JSideris)的答案,或'異步'。兩者都提供了等待任務完成並檢索返回值的方法。 – oefe 2016-09-29 19:44:47

22

什麼有人說類似的 - 我覺得任務是有點簡單(支持如.net 4,可以作爲如下使用.net 4.5):

Task mytask = Task.Run(() => 
{ 
    //Lines of code 
}); 
+0

.net 4中沒有Run方法 – Tommix 2015-12-02 14:14:06

+1

已更正:任務在.net 4中可用,但在.net 4.5中支持「Task.Run」語法。 – JSideris 2016-04-27 02:30:16

相關問題