2011-11-14 6 views
54

Mam następujący kod:Przekazywanie parametru Metoda z zastosowaniem Task.Factory.StartNew

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

private void CheckFiles() 
{ 
    //Do stuff 
} 

Chcę teraz zmienić CheckFiles zaakceptować i całkowitą i odniesienie BlockingCollection

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

mogę” t wydaje się znaleźć sposób na uruchomienie tego zadania, tak jak to zrobiłem powyżej.

Czy możesz pomóc?

Dzięki

Odpowiedz

94

Najlepszym rozwiązaniem jest prawdopodobnie użycie wyrażenia lambda, które zamyka się na zmiennych, które mają być wyświetlane.

Należy jednak zachować ostrożność w tym przypadku, zwłaszcza jeśli wywołujesz to w pętli. (Wspominam o tym, ponieważ twoja zmienna to "ID" i jest to powszechne w tej sytuacji.) Jeśli zamkniesz zmienną w niewłaściwym zakresie, możesz dostać błąd. Aby uzyskać szczegółowe informacje, patrz Eric Lippert's post on the subject. To zazwyczaj wymaga dokonania tymczasowy:

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

Ponadto, jeśli kod jest jak wyżej, należy być ostrożnym przy użyciu wskazówkę LongRunning - z domyślnym scheduler, powoduje to każde zadanie, aby dostać swój własny dedykowany wątek zamiast korzystania z ThreadPool. Jeśli tworzysz wiele zadań, może to mieć negatywny wpływ, ponieważ nie uzyskasz korzyści z ThreadPool. To typowo nastawione dla jednego zadania długo pracuje (stąd jego nazwa), a nie coś, co będzie wdrożony do pracy na przedmiot z kolekcji itp

+0

Dzięki. Zacznę je w pętli. Jednak potrzebuję go jako LongRunning. Mój oryginalny program działał z jednym plikiem, ale teraz musi zrobić kod na wielu plikach. Dlatego muszę podać ID, BlockingCollection, CancellationTokenSoure i StreamReader. Nie dodałem jednak tych dodatkowych parametrów w pytaniu: – Jon

+1

@Jon: Tylko sprawdź zakres tych obiektów ... Właśnie wspomniałem o podpowiedzi LongRunning jako o czymś do rozważenia - powiem, że rzadko jest to dobry pomysł aby używać LongRunning, szczególnie w .NET 4, jeśli uruchamiasz wiele zadań (np. praca w pętli), ponieważ wątek zazwyczaj zapewnia lepsze zachowanie. –

+0

Pętla służy do uruchamiania zadań. Maksymalnie 4-6 – Jon

5

Konstrukt pierwszy parametr jako przykład Action, np

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

Na przejściu jedną liczbę całkowitą zgadzam się z Reed Copsey użytkownika odpowiedź. Jeśli w przyszłości przekażesz bardziej skomplikowane konstrukcje, osobiście chciałbym przekazać wszystkie moje zmienne jako Anonimowy Typ. Będzie to wyglądać mniej więcej tak:

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 
} 

Możesz dowiedzieć się więcej o tym w moim blog