如何将特定类的方法名称作为另一个方法的参数传递

时间:2016-06-16 23:26:02

标签: c# multithreading delegates

我正在尝试编写一个C#方法,它通过传入一个对象并运行其中一个方法来生成线程。

这是一个简单的例子:

class ThreadData {
    private JObject jsonObj;
    private int start;
    private int end;
    public ThreadData(JObject jsonObj, int start, int end) {
        this.jsonObj= jsonObj;
        this.start = start;
        this.end = end;
    }
    public void Calculate() {
        for (int i = start; i < end; i++) {
            // do stuff
        }
    }
    public void Produce() {
        for (int i = start; i < end; i++) {
            // do other stuff
        }
    }
}

class Program {
    static void Main(string[] args) {
        JObject jsonObj= SomeRestAPICall();
        RunInThreads(5, jsonObj, Calculate);
        RunInThreads(5, jsonObj, Produce);
    }

    // ...
}

json对象有n个项目。 RunInThreads方法的目标是生成X个线程,将jsonObj分成相等的X块,并在每个块上运行每个线程。我将方法传递给线程数,json对象以及运行ThreadData类的方法。

private static void RunInThreads(int numOfThreads, JObject object, type functionToRun) {
    int chunks = object.Count() / numOfThreads;
    List<Thread> threads = new List<Thread>();
    for (int i = 1; i <= numOfThreads; i++) {
        int start = (i - 1) * chunks;
        int end = i == numOfThreads? object.Count() : start + chunks;

        ThreadData threadData = new ThreadData(object, start, end);
        Thread thread = new Thread(new ThreadStart(threadData.<FUNCTION>));
        thread.Start();
        threads.Add(thread);
    }
    foreach (Thread t in threads) { t.Join(); }
}

我无法弄清楚如何将函数名称作为参数传递。我会使用代表吗?如果我使用两个单独的方法,我会在每个方法中添加自定义方法名称。例如,对于Calculate()方法,它将是这样的:

private static void CalculateInThreads(int numOfThreads, JObject object) {
    int chunks = object.Count() / numOfThreads;
    List<Thread> threads = new List<Thread>();
    for (int i = 1; i <= numOfThreads; i++) {
        int start = (i - 1) * chunks;
        int end = i == numOfThreads? object.Count() : start + chunks;

        ThreadData threadData = new ThreadData(object);
        Thread thread = new Thread(new ThreadStart(threadData.functionToRun));
        thread.Start();
        threads.Add(thread);
    }
    foreach (Thread t in threads) { t.Join(); }
}

1 个答案:

答案 0 :(得分:3)

我相信这样的事情会起作用:

private static void RunInThreads(int numOfThreads, JObject object, 
                                 Action<ThreadData> functionToRun) {
    int chunks = object.Count() / numOfThreads;
    List<Thread> threads = new List<Thread>();
    for (int i = 1; i <= numOfThreads; i++) {
        int start = (i - 1) * chunks;
        int end = i == numOfThreads? object.Count() : start + chunks;

        ThreadData threadData = new ThreadData(object, start, end);
        Thread thread = new Thread(new ThreadStart(() => functionToRun(threadData));
        thread.Start();
        threads.Add(thread);
    }
    foreach (Thread t in threads) { t.Join(); }
}

你会这样称呼它:

RunInThreads(5, jsonObj, t=>t.Calculate());

解释语法:

Action<ThreadData>Action<T> - 一个预定义的委托,它接受一个输入参数并返回void。

t => t.Calculate()语法是lambda expression,表示委托的实例 - 它基本上是一种定义内联函数的简短方法,它采用单个参数tt的类型推断为ThreadData,因为编译器知道委托是Action<ThreadData>

你可以用更多的按键来写同样的东西:

void DoCalculate(ThreadData data)
{
    data.Calculate();
}
...
RunInThread(5, jsonObj, new Action<ThreadData>(DoCalculate));