2016-11-20 23 views
0

美好的一天。我需要執行一些任務func異步。但如何做到這一點?C#: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; 
} 

因此,在該行.Where(async elem => await IsGoodPersonForSchedule(elem, usedStaff, position))我有一個錯誤:

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> .

,我發現這是解決方案: .Where(elem => IsGoodPersonForSchedule(elem, usedStaff, position).Result) 但它就是這麼奇怪,異步方法的使用結果屬性...它編譯沒有錯誤。也許你知道另一種解決方案

回答

-1

Where必須返回值,因爲如果該行符合條件,它可以斷言它的方式。

這就是這種方式看起來合適的.Where(elem => IsGoodPersonForSchedule(elem, usedStaff, position).Result)

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; 
} 

嗯,無論是這裏有些東西消隱位正在做重要的是,這或可以直接被替換爲:

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

因爲你不能推的任務的一部分,這是很重要一個子查詢中的操作。

然而,如果你有一個非異步IsGoodPersonForSchedule和異步IsGoodPersonForScheduleAsync那麼你就可以在查詢中使用IsGoodPersonForSchedule,將成爲傳遞給數據庫整個查詢的一部分。獲取較大查詢的結果將是一個整體異步。

E.g.讓我們假設你的IsGoodPersonForSchedule更多的東西,如:

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(); 
} 

(這可能是富裕,但我只是想的東西,確實有意義從倉庫異步獲得布爾結果的一個例子)。

然後,如果你也有:

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

這種形式可以作爲一個更廣泛的查詢的一部分,因爲它是一個更廣泛的異步查詢的一部分,那麼它仍然變成了SQL在適當的時候,而不是在C#中執行非異步。

代碼的重複是壞的,但可以解決:

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(); 

我還注意到,您有:

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

這將創建一個具有運行另一個任務在另一個線程而不是處理以前的線程await。它應該是

return JsonConvert.SerializeObject(result); 
+0

有關序列化到JSON創建線程:是的,我同意你的觀點,創造新的線程應該花更多的時間比在當前線程執行此。感謝您對linq中的異步解釋。 – Evgeniy175