2016-11-20 2 views
0

Guten Tag. Ich muss einige Task func async ausführen. Aber wie geht das?C#: async in LINQ

public async Task<string> GetPersonForSchedule(int[] usedStaff, string position) 
{ 
    var result = await staffRepository 
     .GetMany() 
     .Where(async elem => await IsGoodPersonForSchedule(elem, usedStaff, position)) 
     .ToListAsync(); 

    return await Task.Factory.StartNew(() => JsonConvert.SerializeObject(result)); 
} 

private async Task<bool> IsGoodPersonForSchedule(Person person, int[] usedStaff, string position) 
{ 
    //... 
    var currPersonFlights = await flightStaffRepository 
     .GetMany() 
     .Include(elem => elem.Flight) 
     .Where(elem => IsDateSuitable(elem.Flight.FlightDate.Value)) 
     .Include(elem => elem.Flight.Route) 
     .ToListAsync(); 
    //... 
    return true; 
} 

Also, an der Linie .Where(async elem => await IsGoodPersonForSchedule(elem, usedStaff, position)) ich habe einen Fehler:

Cannot convert async lambda expression to delegate type Func<Person, bool> . An async lambda expression may return void, Task or Task, none of which are convertible to Func<Person, bool> .

ich dies als Lösung gefunden: .Where(elem => IsGoodPersonForSchedule(elem, usedStaff, position).Result) Aber es ist so seltsam, Verwendung Ergebnis Eigenschaft async Methode ... Es kompiliert ohne Fehler. Vielleicht kennst du eine andere Lösung?

Antwort

-1

Die Where muss Wert im Gegenzug bekommen, weil dies der Weg ist, es durchsetzen kann, wenn die Zeile die Bedingung erfüllt ist oder nicht.

Das ist ist diese Art und Weise .Where(elem => IsGoodPersonForSchedule(elem, usedStaff, position).Result) Lösung angemessen aussieht.

1
private async Task<bool> IsGoodPersonForSchedule(Person person, int[] usedStaff, string position) 
{ 
    //... 
    var currPersonFlights = await flightStaffRepository 
     .GetMany() 
     .Include(elem => elem.Flight) 
     .Where(elem => IsDateSuitable(elem.Flight.FlightDate.Value)) 
     .Include(elem => elem.Flight.Route) 
     .ToListAsync(); 
    //... 
    return true; 
} 

Eh, entweder etwas Wichtiges hier in den elided Bits getan, oder kann dies nur mit Fassung:

private Task<bool> IsGoodPersonForSchedule(Person person, int[] usedStaff, string position) 
    => Task.FromResult(true) 

Und das ist wichtig, weil Sie nicht die Aufgabe Teil schieben können eine Operation in eine Unterabfrage.

Wenn Sie aber haben eine nicht-Asynchron IsGoodPersonForSchedule und ein asynchrones IsGoodPersonForScheduleAsync dann können Sie IsGoodPersonForSchedule innerhalb Abfragen verwenden und es wird auf die Datenbank Teil der gesamten Abfrage übergeben werden. Erhalten des Ergebnisses der größeren Abfrage wird als Ganzes async sein.

z. nehmen wir an, dass Ihre IsGoodPersonForSchedule war etwas mehr wie:

private Task<bool> IsGoodPersonForScheduleAsync(Person person, int[] usedStaff, string position) 
{ 
    return flightStaffRepository 
     .GetMany() 
     .Include(elem => elem.Flight) 
     .Where(elem => IsDateSuitable(elem.Flight.FlightDate.Value)) 
     .AnyAsync(); 
} 

(was wahrscheinlich gut aus, aber ich will nur ein Beispiel für etwas, das wirklich sinnvoll ein boolean Ergebnis aus dem Repository async bekommt).

Dann, wenn Sie hatte auch:

private bool IsGoodPersonForSchedule(Person person, int[] usedStaff, string position) 
{ 
    return flightStaffRepository 
     .GetMany() 
     .Include(elem => elem.Flight) 
     .Where(elem => IsDateSuitable(elem.Flight.FlightDate.Value)) 
     .Any(); 
} 

Diese Form als Teil einer breiteren Abfrage verwendet werden könnte, und weil sie Teil einer größeren async Abfrage ist dann ist es immer noch in SQL gedreht angebracht, wenn statt ausgeführt nicht-Async innerhalb der C#.

Die Vervielfältigung von Code ist schlecht, aber lösbares:

private IQueryable<Flight> FlightsForPerson(Person person, int[] usedStaff, string position) 
{ 
    return flightStaffRepository 
     .GetMany() 
     .Include(elem => elem.Flight) 
     .Where(elem => IsDateSuitable(elem.Flight.FlightDate.Value)); 
} 

private Task<bool> IsGoodPersonForScheduleAsync(Person person, int[] usedStaff, string position) 
=> FlightsForPerson(person, usedStaff, position).AnyAsync(); 

private bool IsGoodPersonForSchedule(Person person, int[] usedStaff, string position) 
=> FlightsForPerson(person, usedStaff, position).Any(); 

ich auch möchte anmerken, dass Sie haben:

return await Task.Factory.StartNew(() => JsonConvert.SerializeObject(result)); 

Diese noch eine weitere Aufgabe erstellen wird, die ausgeführt werden muss auf einem anderen Thread statt der Thread die vorherigen await Handhabung. Es sollte

sein
+0

Über das Erstellen von Thread für serialisieren zu JSON: yep, ich stimme Ihnen zu, Erstellen neuer Thread sollte mehr Zeit als die Ausführung in aktuellen Thread dauern. Vielen Dank für Erklärung über async in Linq. – Evgeniy175