【问题标题】:Multithreading in C#: How can I pass a function name to another function to start a new thread?C# 中的多线程:如何将函数名传递给另一个函数以启动新线程?
【发布时间】:2009-02-18 09:05:47
【问题描述】:

我在我的 C# 代码中使用多线程,如下所示:

Thread startThread;

public void NewThread()
{
   ThreadStart starter = delegate { foo(); };
   startThread = new Thread(starter);
   startThread.Start();
}

private void foo()
{
   //do some work
}

然后在我的应用程序中调用 NewThread() 来运行新线程。

但是现在我在每个类上都有很多线程,每个类都有一个 NewThread() ,我正在考虑将它移动到一个静态 Util 类,并在每次我想要一个新线程时将函数名传递给它那个函数。

你知道这是最好的方法吗?如果知道,我如何将函数名作为参数传递给它?

【问题讨论】:

    标签: c# .net multithreading oop


    【解决方案1】:

    好吧,既然方法是私有的,那么调用者知道方法名称是否有意义?如果它是公开的,您可以将方法传入:

    public void NewThread(Action task)
    {
       ThreadStart starter = delegate { task(); };
       startThread = new Thread(starter);
       startThread.Name = task.Method.Name;
       startSpoolerThread.Start();
    }
    
    public void foo()
    {
       //do some work
    }
    
    NewThread(obj.foo);
    

    但是,对于私有方法,我怀疑枚举/开关是最好的选择...

    NewThread(TasktType.Foo);
    

    或者,您可以通过反射获取方法...

    public void NewThread(string name)
    {
        MethodInfo method = GetType().GetMethod(name,
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
            null, Type.EmptyTypes, null);
        ThreadStart starter = delegate { method.Invoke(this, null); };
        // etc (note: no point using Delegate.CreateDelegate for a 1-call usage
    

    【讨论】:

      【解决方案2】:

      除非您明确创建线程有特定原因,否则为什么不使用线程池? Threadpool.QueueUserWorkItem 方法将委托作为要执行的工作单元。委托是一种特定类型,但您可以像在示例中那样将自己的委托调用包装在其中。除非您需要精细控制或取消,否则通常最好使用线程池而不是自己启动线程。

      【讨论】:

        【解决方案3】:

        我建议您也考虑查看并行扩展任务 API 的 CTP;你没有提到你为什么需要一个线程,但他们已经自动化了大部分 here's a link to their blog

        【讨论】:

          【解决方案4】:

          看看下面关于 Codeproject "Poor Man's Parallel.ForEach Iterator" 的文章。我认为这正是您正在寻找的。非常容易使用。

          如需更强大的功能,请查看Power Threading Library

          【讨论】:

            【解决方案5】:

            或者,如果您正在开发 Win.Forms 或类似的基于 GUI 的应用程序,我建议您使用 BackgroundWorker。它会为您处理大多数与线程相关的事件的编组,并且中止的复杂性也要低得多(如果这是您需要做的事情)。

            【讨论】:

              【解决方案6】:

              委托已经提供了一种异步执行它们的方法。例如:

              delegate void dowork();
              private static void WorkDone(IAsyncResult result)
              {
                 ((dowork)result.AsyncState).EndInvoke(result);
                  // this function is called when the delegate completes
              }
              public void Start()
              {
                  dowork dw = delegate {// code in this block has it's own thread };
                  dw.BeginInvoke(WorkDone, null);
              }
              

              因此,为了将函数指针传递给其他任何东西,您只需要创建一个具有正确签名的委托(在这种情况下,我使用了一个匿名方法,但您可以使用具有正确签名的任何函数)并将其称为 BeginInvoke方法,传递一个完成后将被调用的函数。然后,该函数必须在原始委托上调用 EndInvoke,该委托在结果参数中传递给 WorkDone 函数。

              【讨论】:

                猜你喜欢
                • 2016-10-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-12-30
                • 1970-01-01
                • 2019-04-25
                • 2012-02-18
                相关资源
                最近更新 更多