2017-11-15 1 views
-1

Ich folge this guide on BlockingCollection, um ein Producer/Consumer-Muster zu implementieren, kann aber meine Aufgaben nicht parallel auf der Herstellerseite ausführen.Hinzufügen von Elementen im Producer/Consumer-Muster async using BlockingCollection

Das Problem ist mein foreach Block wird sequenziell ausgeführt. Von this question, verstehe ich, dass ich Projekt die Sammlung von PropertyLien<T> als Task s. Wie ist das gemacht?

// PropertyLien<T> is a class that models an asset (house/building/etc) 
var googleAddresses = new BlockingCollection<Tuple<PropertyLien<string>, IEnumerable<GoogleAddress>>>() 

// Consumer Threads 
var consumer = Task.Run(() => { 
    while(!googleAddresses.IsCompleted) { 
     var adr = googleAddresses.Take(); 
     // Do work 
    } 

    Console.WriteLine("No more addresses to process"); 
}); 

// Producer Threads 
var producer = Task.Factory.StartNew(async() => { 
    // TODO: PROBLEM here, this is executing synchronously 
    foreach(PropertyLien<string> property in properties) { 
     try { 
      // See: https://www.nuget.org/packages/Geocoding.net/ 
      await geocoder.GeocodeAsync(property.Address) 
       .ContinueWith(task => { 
        var googResults = task.Result; 
        googleAddresses.Add(property, googResults); 
       }); 
     } 
     catch {} 
    } 
    googleAddresses.CompleteAdding(); 
}); 

// Need to wait for both tasks to complete. 
Task.WaitAll(producer, consumer); 
+1

Sie 'erwarten nicht geocoder.GeocodeAsync'. Stattdessen lege alle Aufgaben in eine Liste ('yourList.Add (geocoder.GeocodeAsync (....))') und erwarte 'task.WhenAll (yourList)'. – Evk

Antwort

0

Dank @Evk, dies ist die Antwort:

// Producer Threads 
var producer = Task.Factory.StartNew(async() => { 
    var tasks = properties.Select(property => { 
     return geocoder.GeocodeAsync(property.Address) 
      .ContinueWith(task => { 
       // Do work 
      }); 
    }); 

    await Task.WhenAll(tasks); 
    googleAddresses.CompleteAdding(); 
}); 
Verwandte Themen