2015-10-15 1 views
4

В следующем коде я передаю действие, объявленное вне StartNew, выглядит нормально.Использование Task.Factory.StartNew с действием, которое принимает один параметр int

Action ac =() => { Console.WriteLine("Executing Action in Task 7!"); }; 
var t7 = Task.Factory.StartNew(ac ); 
Task.WaitAny(t7); 

Но я хочу передать параметр Int к действию (я хочу объявить действие вне StartNew).

Action<int> ac2 = (n) => 
{ 
    Console.WriteLine("Executing Action with 1 parameter = {0}", n);    
}; 
var t9 = Task.Factory.StartNew( ac2 , 4); //Problem here???? 

Следующий код в порядке, но я не хочу использовать действие таким образом. Я хочу определить действие снаружи и вызвать его внутри StartNew(), как указано выше. Как использовать ac2, чтобы получить тот же результат, что и код ниже.

var t8 = Task.Factory.StartNew( (n) => 
{ 
    Console.WriteLine("Executing Action in Task 8!"); 
    Console.WriteLine("Param pass {0}", n); 

}, 4); 
Task.WaitAny(t8); 
+3

Используйте 'Action ' вместо 'Action '. – PetSerAl

+2

Отключить тему, но обычно вы должны использовать 'Task.Run()' – MickyD

+0

Вы можете сделать это: 'var t9 = Task.Factory.StartNew (() => {ac2 (4);});' – Rob

ответ

1

Вы можете использовать дополнительные функции делегата:

Func<Action<int>, int, Action> createDelegate = (action, arg) => 
{ 
    return() => action(arg); 
}; 
Task.Factory.StartNew(createDelegate(ac2, 2)); 
0

Использование Action<object> вместо.

Action<object> ac2 = (n) => 
{ 
    Console.WriteLine("Executing Action with 1 parameter = {0}", n);    
}; 

var t9 = Task.Factory.StartNew(ac2, 4); 

Метод StartNew() не имеет перегрузки, чтобы принять Action<T> или Action<int> для этого случая. Допускается только Action<object>.

0

Ну вы можете использовать перегрузку, которая принимает object отправить Tuple<T1, T2>:

 Action<int> ac2 = (n) => 
     { 
      Console.WriteLine("Executing Action with 1 parameter = {0}", n);    
     }; 

     var _data = new Tuple<Action<int>, int>(ac2, 4); 

     var t9 = Task.Factory.StartNew((obj) => 
      { 
       var data = obj as Tuple<Action<int>, int>; 
       data.Item1(data.Item2); 
      }, _data); 
4

Не уверен, почему существующие ответы настолько сложны:

Task.Factory.StartNew(() => ac(4)); 

Это все, что нужно. Просто вызовите функцию, завернутую в лямбда. Лучше использовать Task.Run, а также:

Task.Run(() => ac(4)); 

StartNew способен принимать еще один аргумент object, но это очень специализированный API, который является излишне запутанным и следует использовать очень редко. Это позволяет избежать выделения двух небольших и короткоживущих объектов. Не используйте его.

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