Подтвердить что ты не робот

Передача параметра метода с помощью Task.Factory.StartNew

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

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

private void CheckFiles()
{
  //Do stuff
}

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

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

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

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

Спасибо

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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
}

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

Ответ 4

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

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

Ответ 5

Попробуйте это,

        var arg = new { i = 123, j = 456 };
        var task = new TaskFactory().StartNew(new Func<dynamic, int>((argument) =>
        {
            dynamic x = argument.i * argument.j;
            return x;
        }), arg, CancellationToken.None, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
        task.Wait();
        var result = task.Result;