在C#中将lambda表达式或匿名函数转换为委托对象的最直接方法是什么?

时间:2011-01-08 10:13:37

标签: c# multithreading lambda delegates expression

我正在编写一些代码来解决正在进行的系统中的线程安全问题,并且推荐的方法之一是使用委托来解决跨线程问题。但由于某种原因,我不喜欢为可能需要拦截的每个可能的操作定义一个委托,因此更喜欢使用匿名方法或lambda表达式,但我编译器拒绝将任何这些操作转换为系统。委托对象。

这是否有捷径?

  

if(someListBox.InvokeRequired)
  {
    someListBox.Invoke(Some_System.Delegate_Object,new object [] {item});
  }
  否则
     someListBox.Items.Add(项目);

我想要类似......

  

if(someListBox.InvokeRequired)
  {
    someListBox.Invoke((i)=> {someListBox.Items.Add(i);},new object [] {item});

  }
  否则
     someListBox.Items.Add(项目);

2 个答案:

答案 0 :(得分: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();

答案 1 :(得分: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); });       
}