Передача параметра метода с помощью Task.Factory.StartNew - PullRequest
58 голосов
/ 15 ноября 2011

У меня есть следующий код:

var task = Task.Factory.StartNew(CheckFiles, cancelCheckFile.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);

private void CheckFiles()
{
  //Do stuff
}

Теперь я хочу изменить CheckFiles так, чтобы он принимал целое число и ссылку BlockingCollection

private void CheckFiles(int InputID, BlockingCollection<string> BlockingDataCollection)
{
  //Do stuff
}

Кажется, я не могу найти способ запустить эту задачу, как я делал выше.

Вы можете помочь?

Спасибо

Ответы [ 4 ]

99 голосов
/ 15 ноября 2011

Лучшим вариантом, вероятно, является использование лямбда-выражения, закрывающего переменные, которые вы хотите отобразить.

Однако будьте осторожны в этом случае, особенно если вы вызываете это в цикле. (Я упоминаю об этом, поскольку ваша переменная является «идентификатором», и это обычно встречается в этой ситуации.) Если вы закроете переменную в неправильной области, вы можете получить ошибку. Подробнее см. пост Эрика Липперта по теме . Обычно для этого требуется сделать временное:

foreach(int id in myIdsToCheck)
{
    int tempId = id; // Make a temporary here!
    Task.Factory.StartNew( () => CheckFiles(tempId, theBlockingCollection),
         cancelCheckFile.Token, 
         TaskCreationOptions.LongRunning, 
         TaskScheduler.Default);
}

Кроме того, если ваш код подобен приведенному выше, вы должны быть осторожны с подсказкой LongRunning - с планировщиком по умолчанию, это заставляет каждую задачу получать свой собственный выделенный поток вместо использования ThreadPool. Если вы создаете много задач, это может оказать негативное влияние, поскольку вы не получите преимуществ ThreadPool. Как правило, он предназначен для одной длительной задачи (отсюда и ее имя), а не для реализации над элементом коллекции и т. Д.

19 голосов
/ 16 июля 2013
class Program
{
    static void Main(string[] args)
    {
        Task.Factory.StartNew(() => MyMethod("param value"));
    }

    private static void MyMethod(string p)
    {
        Console.WriteLine(p);
    }
}
6 голосов
/ 13 февраля 2014

Для передачи единственного целого числа я согласен с ответом Рида Копси. Если в будущем вы собираетесь передавать более сложные конструкции, мне лично нравится передавать все мои переменные как анонимный тип. Это будет выглядеть примерно так:

foreach(int id in myIdsToCheck)
{
    Task.Factory.StartNew( (Object obj) => 
        {
           var data = (dynamic)obj;
           CheckFiles(data.id, theBlockingCollection,
               cancelCheckFile.Token, 
               TaskCreationOptions.LongRunning, 
               TaskScheduler.Default);
        }, new { id = id }); // Parameter value
}

Подробнее об этом можно узнать в моем блоге

5 голосов
/ 15 ноября 2011

Создайте первый параметр как экземпляр Action, например,

var inputID = 123;
var col = new BlockingDataCollection();
var task = Task.Factory.StartNew(
    () => CheckFiles(inputID, col),
    cancelCheckFile.Token,
    TaskCreationOptions.LongRunning,
    TaskScheduler.Default);
...