Передача параметра метода с помощью задачи.Фабрика.StartNew


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

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 55

4 ответа:

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

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

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. Он обычно ориентирован на одну длительную задачу (отсюда и ее название), а не на то, что было бы реализовано для работы над предмет коллекции и др.

class Program
{
    static void Main(string[] args)
    {
        Task.Factory.StartNew(() => MyMethod("param value"));
    }

    private static void MyMethod(string p)
    {
        Console.WriteLine(p);
    }
}

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

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
}

вы можете узнать больше об этом на моем блог

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

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