2011-11-14 9 views
54

kullanan bir yöntem parametre aktarımı Aşağıdaki kodu vardır:Task.Factory.StartNew

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

private void CheckFiles() 
{ 
    //Do stuff 
} 

Şimdi kabul CheckFiles değiştirme istiyor ve tamsayı ve bir BlockingCollection referans

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

dayana Yukarıda yaptığım gibi bu görevi başlatmak için bir yol bulmak gibi görünüyor.

Yardımcı olabilir misiniz?

sayesinde

cevap

94

En iyi seçenek, görüntülemek istediğiniz değişkenleri kapatan bir lambda ifadesi kullanmaktır. Ancak, özellikle de bunu bir döngüde çağırıyorsanız, bu durumda dikkatli olun. (Değişkeniniz bir "ID" olduğu için bunu belirtiyorum ve bu durum bu durumda yaygındır.) Değişkeni yanlış kapsamda kapatırsanız, bir hata alabilirsiniz. Ayrıntılar için bkz. Eric Lippert's post on the subject. Varsayılan zamanlayıcı ile bu yerine kendi özel iplik almak için her görevi neden olur - kodunuzu yukarıdaki gibi ise

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

Ayrıca, sen LongRunning ipucu kullanarak dikkatli olmalıdır: Bu genellikle geçici bir yapım gerektirir ThreadPool kullanma. Birçok görev oluşturuyorsanız, ThreadPool'un avantajlarını alamayacağınız için bunun olumsuz bir etkisi olması muhtemeldir. Genellikle Reed Copsey en katılıyorum tek tamsayı geçirerek vb tek, uzun süren görevi (adını aldığı) bir koleksiyon bir öğe üzerinde çalışmak için uygulanacağına dair değil, bir şey

+0

teşekkürler

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 } 

Bu konuda daha fazla bilgi edinebilirsiniz: Böyle bir şey olacaktır. Onları bir döngü içinde başlatacağım. Ancak buna LongRunning olarak ihtiyacım var. Orijinal programım tek bir dosya ile çalıştı ama şimdi çok sayıda dosya üzerinde bazı kodları yapmak gerekiyor. Bu yüzden ID, BlockingCollection, CancellationTokenSoure ve StreamReader'ı geçmem gerekiyor. Bu ekstra metod parametrelerini bu soruya eklemedim, ancak – Jon

+1

@ Jon: Sadece bu nesnelerin kapsamını kontrol ettiğinizden emin olun ... Uzun bir süredir düşündüğünüz bir şey olarak LongRunning ipucundan bahsetmiştim - bunun nadiren iyi bir fikir olduğunu söyleyeceğim birçok görevi başlatıyorsanız (ör: bir döngüde çalışıyorsanız) LongRunning'ı, özellikle .NET 4'te kullanmak için, threadpool genellikle daha iyi bir davranış sağlayacaktır. –

+0

Döngü sadece görevleri başlatmak içindir. En fazla 4-6 – Jon

5

örneğin Action bir örneği, birinci parametre Construct

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

için içindir Cevap. Gelecekte daha karmaşık yapıları geçecekseniz, tüm değişkenlerimi Anonim Tip olarak iletmeyi seviyorum. Benim blog