2016-06-16 2 views
1

Я пытаюсь написать метод 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 имеет п число элементов. Цель метода 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(); } 
} 

ответ

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> - предварительный вариант d, который принимает один входной параметр и возвращает void.

Синтаксис t => t.Calculate() является lambda expression, который представляет собой экземпляр делегата - это в основном короткий путь, чтобы определить функцию инлайн, которая принимает один параметр t. Предполагается, что тип t равен ThreadData, поскольку компилятор знает, что делегат является Action<ThreadData>.

Вы могли бы написать то же самое с более нажатиями, как это:

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

Высокий - спасибо! Именно то, что я искал. Можете ли вы объяснить синтаксис «t => t.Calculate()»? Что здесь означает «t» и как оно известно, Calculate() является допустимым методом в этом контексте? – Nick

+0

Нет проблем! Под редакцией! – Blorgbeard

+0

Спасибо, что объяснил это. – Nick

Смежные вопросы