2011-11-14 24 views
54

I tienen el siguiente código:Pasando un parámetro de método usando Task.Factory.StartNew

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

private void CheckFiles() 
{ 
    //Do stuff 
} 

ahora quiero modificar CheckFiles para aceptar y número entero y una referencia BlockingCollection

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

I puede' Parece encontrar una manera de comenzar esta tarea como lo hice anteriormente.

¿Puede ayudarnos?

Gracias

Respuesta

94

La mejor opción es probablemente utilizar una expresión lambda que cierre las variables que desea visualizar.

Sin embargo, tenga cuidado en este caso, especialmente si está llamando esto en un bucle. (Menciono esto ya que su variable es una "ID", y esto es común en esta situación). Si cierra la variable en el ámbito incorrecto, puede obtener un error. Para más detalles, vea Eric Lippert's post on the subject. Esto normalmente requiere hacer un temporal:

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

Además, si su código es igual que el anterior, se debe tener cuidado con el uso de la pista LongRunning - con el programador predeterminado, esto hace que cada tarea de conseguir su propio hilo dedicado en lugar de usar ThreadPool. Si está creando muchas tareas, es probable que esto tenga un impacto negativo ya que no obtendrá las ventajas de ThreadPool. Es normalmente orientados para una sola, la tarea de larga ejecución (de ahí su nombre), no es algo que se pondría en práctica para trabajar en un elemento de una colección, etc.

+0

Gracias. Los iniciaré en un bucle. Sin embargo, lo necesito como LongRunning. Mi programa original funcionaba con un archivo pero ahora necesita hacer un código en numerosos archivos. Por lo tanto, necesito pasar el ID, BlockingCollection, CancellationTokenSoure y StreamReader. No agregué esos parámetros de método adicionales en la pregunta sin embargo – Jon

+1

@Jon: Solo asegúrate de verificar el alcance de esos objetos ... Acabo de mencionar la sugerencia de LongRunning como algo para que consideres - Diré que rara vez es una buena idea utilizar LongRunning, especialmente en .NET 4, si está iniciando muchas tareas (es decir, trabajando en un bucle), ya que el threadpool generalmente proporcionará un mejor comportamiento. –

+0

El ciclo es solo para comenzar las tareas. Máximo de 4-6 – Jon

5

construir el primer parámetro como una instancia de Action, por ejemplo

var inputID = 123; 
var col = new BlockingDataCollection(); 
var task = Task.Factory.StartNew(
    () => CheckFiles(inputID, col), 
    cancelCheckFile.Token, 
    TaskCreationOptions.LongRunning, 
    TaskScheduler.Default); 
17
class Program 
{ 
    static void Main(string[] args) 
    { 
     Task.Factory.StartNew(() => MyMethod("param value")); 
    } 

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

Para pasar un solo entero Estoy de acuerdo con Reed Copsey de responder. Si en el futuro va a pasar constucts más complicados, personalmente me gusta pasar todas mis variables como un tipo anónimo. Se verá algo como esto:

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 
} 

Usted puede aprender más sobre esto en mi blog

Cuestiones relacionadas