Odnosi się to do http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266988.aspx , http://winrtstoragehelper.codeplex.com/ , sklepu z aplikacjami Windows 8 i .net 4.5
Oto mój punkt widzenia na to:
Funkcja języka asynchronicznego / oczekującego sprawia, że wiele rzeczy jest dość łatwych, ale wprowadza również scenariusz, z którym rzadko się zdarzało, zanim było tak łatwe w użyciu wywołania asynchroniczne: ponowne wejście.
Jest to szczególnie prawdziwe w przypadku procedur obsługi zdarzeń, ponieważ w przypadku wielu zdarzeń nie masz pojęcia, co się dzieje po powrocie z procedury obsługi zdarzeń. Jedną z rzeczy, które mogą się zdarzyć, jest to, że metoda asynchroniczna, na którą czekasz w pierwszej procedurze obsługi zdarzeń, jest wywoływana z innej procedury obsługi zdarzeń, która wciąż znajduje się w tym samym wątku.
Oto prawdziwy scenariusz, z którym spotkałem się w aplikacji Windows 8 App Store: Moja aplikacja ma dwie ramki: wchodzenie i wychodzenie z ramki Chcę załadować / zabezpieczyć niektóre dane do pliku / pamięci. Zdarzenia OnNavigatedTo / From służą do zapisywania i ładowania. Zapisywanie i ładowanie odbywa się za pomocą funkcji narzędzia asynchronicznego (np. Http://winrtstoragehelper.codeplex.com/ ). Podczas nawigacji z ramki 1 do ramki 2 lub w innym kierunku, ładowanie asynchroniczne i operacje bezpieczne są wywoływane i oczekiwane. Procedury obsługi zdarzeń stają się asynchroniczne zwracając void => nie można się doczekać.
Jednak pierwsza operacja otwierania pliku (powiedzmy: wewnątrz funkcji składowania) narzędzia jest również asynchroniczna, więc pierwsze oczekiwanie zwraca kontrolę do frameworka, który później wywołuje inne narzędzie (ładowanie) za pośrednictwem drugiej procedury obsługi zdarzeń. Ładunek próbuje teraz otworzyć ten sam plik, a jeśli plik jest już otwarty dla operacji składowania, kończy się niepowodzeniem z wyjątkiem ACCESSDENIED.
Minimalnym rozwiązaniem dla mnie jest zabezpieczenie dostępu do pliku za pomocą przy użyciu i AsyncLock.
private static readonly AsyncLock m_lock = new AsyncLock();
...
using (await m_lock.LockAsync())
{
file = await folder.GetFileAsync(fileName);
IRandomAccessStream readStream = await file.OpenAsync(FileAccessMode.Read);
using (Stream inStream = Task.Run(() => readStream.AsStreamForRead()).Result)
{
return (T)serializer.Deserialize(inStream);
}
}
Należy pamiętać, że jego blokada zasadniczo blokuje wszystkie operacje na plikach dla narzędzia za pomocą tylko jednej blokady, co jest niepotrzebnie silne, ale działa dobrze w moim scenariuszu.
Oto mój projekt testowy: aplikacja Windows 8 App Store z kilkoma testowymi wywołaniami oryginalnej wersji z http://winrtstoragehelper.codeplex.com/ i mojej zmodyfikowanej wersji, która używa AsyncLock z Stephen Toub http: //blogs.msdn. com / b / pfxteam / archive / 2012/02/12 / 10266988.aspx .
Czy mogę również zasugerować ten link:
http://www.hanselman.com/blog/ComparingTwoTechniquesInNETAsynchronousCoordinationPrimitives.aspx