Od jakiegoś czasu próbowałem uzyskać coś, co moim zdaniem byłoby proste przy pracy z .NET 4.5
Chcę odpalić dwa długotrwałe zadania w tym samym czasie i zebrać
wyniki w najlepszy sposób C # 4.5 (RTM)
Poniższe działa, ale mi się to nie podoba, ponieważ:
- Chcę
Sleep
być metodą asynchroniczną, aby mogła miećawait
inne metody - Po prostu wygląda niezdarnie
Task.Run()
- Nie sądzę, żeby to w ogóle korzystało z nowych funkcji językowych!
Kod roboczy:
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Task.Run(() => Sleep(5000));
var task2 = Task.Run(() => Sleep(3000));
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}
private static int Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
Console.WriteLine("Sleeping for " + ms + " FINISHED");
return ms;
}
Niedziałający kod:
Aktualizacja: To faktycznie działa i jest właściwy sposób, aby to zrobić, jedynym problemem jest Thread.Sleep
Ten kod nie działa, ponieważ wywołanie Sleep(5000)
natychmiast uruchamia zadanie, więc Sleep(1000)
nie jest uruchamiane, dopóki nie zostanie ukończone. To prawda, mimo że Sleep
jest async
i nie używam await
ani nie dzwonię.Result
zbyt wcześnie.
Pomyślałem, że może istnieje sposób, aby Task<T>
wywołać async
metodę niedziałającą , wywołując metodę, aby móc następnie wywołać Start()
dwa zadania, ale nie mogę dowiedzieć się, jak uzyskać a Task<T>
od wywołania metody asynchronicznej.
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Sleep(5000); // blocks
var task2 = Sleep(1000);
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for " + totalSlept + " ms");
}
private static async Task<int> Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
return ms;
}
źródło
task1.Result
nie o godzinie,var task1 = Sleep(5000)
ponieważ metoda uśpienia bez słowa kluczowego await jest synchroniczna.Odpowiedzi:
Do programowania asynchronicznego należy użyć Task.Delay zamiast Sleep, a następnie użyć Task.WhenAll, aby połączyć wyniki zadania. Zadania działałyby równolegle.
źródło
źródło
Go
metoda wywołującego jest synchroniczna, ale chce wykonać dwa niezależne zadania asynchronicznie (tj. Żadne z nich nie musi kończyć się przed drugim, ale oba muszą zakończyć się przed kontynuacją wykonywania),Task.WaitAll
byłoby lepiej i nie nie potrzebuje słowa kluczowego await, więc nie potrzeba, abyGo
metoda wywołująca była sama asynchroniczna. Żadne z podejść nie jest lepsze, to tylko kwestia celu.async void LongTask1() {...}
Metoda unieważnienia : nie ma właściwości Task.Result. Użyj zadanie bez T w takim przypadku:async Task LongTask1()
.Task<TResult> t1 = LongTask1();
i teraz mamt1.Result
.<TResult>
to zwracany typ wyniku. Abyreturn <TResult>
to zadziałało, potrzebujesz w swojej metodzie.t1
it2
zmiennych, możesz użyćnew Task(...)
. Na przykład:int int1 = 0; await Task.WhenAll(new Task(async () => { int1 = await LongTask1(); }));
. Jednym z haczyków tego podejścia jest to, że kompilator nie rozpozna, że zmienna została przypisana i potraktuje ją jako nieprzypisaną, jeśli nie nadasz jej wartości początkowej.Chociaż twoja
Sleep
metoda jest asynchroniczna,Thread.Sleep
nie jest. Cała idea asynchronizacji polega na ponownym użyciu pojedynczego wątku, a nie na rozpoczynaniu wielu wątków. Ponieważ zablokowałeś używanie synchronicznego wywołania Thread.Sleep, to nie zadziała.Zakładam, że
Thread.Sleep
jest to uproszczenie tego, co naprawdę chcesz zrobić. Czy Twoja rzeczywista implementacja może być zakodowana jako metody asynchroniczne?Jeśli musisz uruchomić wiele synchronicznych wywołań blokujących, spójrz gdzie indziej, myślę!
źródło
var x = y()
i nie,var x=await y()
luby().wait()
nadal to poczekaj do końca, a jeśli asynchronizacja nie poradzi sobie sama z tym, co mam zrobić? PAMIĘTAJ, że y jest ozdobione asynchronicznie i spodziewam się, że zrobi wszystko, gdy wszystko, a nie dokładnie tam, gdzie jest przypisane, EDYTUJ: ja tylko wtedy, gdy mój partner powiedział, spróbujmyTask.Factory
, a on powiedział, że zadziałało, gdy się wyrwę strona tej klasyAby odpowiedzieć na to pytanie:
możesz przepisać
Sleep
funkcję w ten sposób:uruchomienie tego kodu spowoduje wyświetlenie:
źródło
Teraz jest weekend !
źródło
Ten artykuł pomógł wyjaśnić wiele rzeczy. Jest w stylu FAQ.
Async / Await - często zadawane pytania
Ta część wyjaśnia, dlaczego
Thread.Sleep
działa na tym samym oryginalnym wątku - co prowadzi do mojego początkowego zamieszania.źródło