C# 如何使用.NET操作执行参数数目未知的方法?

C# 如何使用.NET操作执行参数数目未知的方法?,c#,multithreading,lambda,action,C#,Multithreading,Lambda,Action,我想在工作线程上执行一些操作,同时向用户显示进度条。我已经创建了一个类 public class ProgressBar { public void StartAsyncTask(Action action) { Task t = new Task(action); t.start(); } } 我发现我可以通过以下方式将任何方法发送到StartAsyncTask: ProgressBar pb = new ProgressBar(); pb.

我想在工作线程上执行一些操作,同时向用户显示进度条。我已经创建了一个类

public class ProgressBar
{
   public void StartAsyncTask(Action action)
   {
      Task t = new Task(action);
      t.start();
   }
}
我发现我可以通过以下方式将任何方法发送到
StartAsyncTask

  ProgressBar pb = new ProgressBar();
  pb.StartAsyncTask( () => DoSomething(15, "something"));

  public void DoSomething(int i, string s)
   {
      //do something
   }
首先,我似乎无法理解什么是lambda表达式-
()=>
,以及lambda表达式是如何翻译的,以及
操作
对象是如何传递给具有未知参数数的委托的

我想在ProgressBar中使用
BackgroundWorker
,但在这种情况下,我需要调用该操作。比如说:

void m_backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    Action action = e.Argument as Action; //same action here passed through EventArgs
   //but already in a worker thread so no need for the Task object 

   //and now i need to somehow invoke the action object but i don't know what the parameters are. 

   action.Invoke( ? ); 
}
在第一个示例中,如何在不知道
StartAsyncTask(action-action)
方法中的参数的情况下执行操作

在这种情况下,为什么调用操作时需要知道参数

关于如何/为什么/何时使用“
操作
”的所有内容我都不清楚,即使我阅读了MSDN文档和这里的一些其他线程。
这方面的任何信息都会对我有所帮助。

我觉得你有点想得太多了。因此,让我们从顶部开始:

  • lambda表达式是引用方法执行的符号。例如:

     x => x + 3
    
    在最基本的级别上,这表示一个函数,它接受1个输入,
    x
    ,然后返回一个等于
    x+3
    的值。所以在你的情况下,你的表情:

    () => DoSomething(15, "Something")
    
    表示采用0个参数的方法,然后调用方法
    DoSomething(15,“Something”)
    。编译器正在幕后为您将其转换为
    Func
    Action
    委托。因此,它实际上是:

    new Action(delegate()
    {
        DoSomething(15, "Something")
    }); 
    
    上面简单表达式的编译器重写为:

    new Func<int, int>(delegate(int x)
    {
        return x + 3;
    });
    
    因此,如果您有一个给定的
    Action
    实例,只需使用
    ()
    语法调用它即可,因为
    Action
    是一个接受0个参数且不返回任何内容的委托

    函数同样简单:

    Func<int, int> previousGuy = x => x + 3;
    var result = previousGuy(3); // result is 6
    
    所有数据都被捕获到方法的闭包中,因此被保存。因此,如果您能够使用
    e.Argument
    属性将
    操作
    传递给事件,那么您需要做的就是调用
    (e.Argument as Action)(


  • 您不能在该委托上使用
    DynamicInvoke()
    (它将
    params object[]args
    作为参数)


    调用时需要知道参数。。否则(如果可能不传递参数),函数将不会传递任何参数。。因此,使您的第一个
    参数。Something
    调用抛出
    NullReferenceException
    Func<int, int> previousGuy = x => x + 3;
    var result = previousGuy(3); // result is 6
    
    var myAction = new Action(() =>
         {
              // Some Complex Logic
              DoSomething(15, "Something");
              // More Complex Logic, etc
         });
    
    InvokeLater(myAction);
    
    public void InvokeLater(Action action)
    {
          action();
    }
    
    action.DynamicInvoke(arg1, arg2, arg3 );