2011-01-08 51 views
0

我正在編寫一些代碼來解決正在處理的系統中的線程安全問題,其中一種推薦的方法是使用代理來解決跨線程問題。但出於某種原因,我不喜歡爲每一個可能需要攔截的操作定義一個委託,因此更喜歡使用匿名方法或lambda表達式,但是編譯器拒絕將其中任何一個轉換爲System。委託對象。什麼是轉換lambda表達式或匿名函數到C#中委託對象的最直接的方法?

這是否有捷徑?

如果(someListBox.InvokeRequired)
{
someListBox.Invoke(Some_System.Delegate_Object,新的對象[] {項});
}
else
someListBox.Items.Add(item);

我想是這樣......

如果(someListBox.InvokeRequired)
{
someListBox.Invoke((I)=> {someListBox.Items.Add(我);} ,new object [] {item});
}
else
someListBox.Items.Add(item);

回答

1

你的問題之一是編譯器不能推斷你的lamda的參數類型。即使對於給定的參數簽名,也有無限多的潛在委託類型。所以你需要明確地給出一個類型。如果您不關心參數名稱,則Action<...>Func<...>是典型的候選項。

我認爲這應該工作:

`someListBox.Invoke((Action<int>)((i) => {listviewResults.Items.Add(i); }), new object[] {item});` 

還是在重構的形式,以避免重複自己:

Action<int> myAction=(i) => listviewResults.Items.Add(i); 
if (someListBox.InvokeRequired) 
{ 
    someListBox.Invoke(myAction, new object[] {item}); 
} 
else 
    myAction(item); 

而且我看不出有任何理由,你爲什麼會想有i作爲一個參數全部:

Action myAction =() => listviewResults.Items.Add(item); 
if (someListBox.InvokeRequired) 
{ 
    someListBox.Invoke(myAction); 
} 
else 
    myAction(); 
+0

謝謝,不知道這項技術直接使用Action;第二個爲我工作。事實上C#爲我們節省了很多痛苦:) – nemesisfixx 2011-01-08 10:59:19

1

您想要的方法的缺點是,這項工作將在兩個地方實施。一種替代方法可能如下所示:

private void AddItemToListView(ListViewItem item, ListView listView) 
{ 
    if (listView.InvokeRequired) 
    { 
     listView.BeginInvoke((Action)delegate { AddItemToListView(item, listView); }); 
    } 
    else 
    { 
     listView.Items.Add(item); 
    } 
} 

然後,您可以再次討論此代碼的執行頻率。如果不是非常多,也許它能夠更好地通過不檢查InvokeRequired把它簡化一下,而是始終包裹在傳遞給BeginInvoke委託電話:

private void AddItemToListView(ListViewItem item, ListView listView) 
{ 
    listView.BeginInvoke((Action)delegate { listView.Items.Add(item); });  
} 
相關問題