Proszę zauważyć następujący kod trywialny:Dlaczego Task.henAny nie rzuca oczekiwany TimeoutException?
class Program
{
static void Main()
{
var sw = new Stopwatch();
sw.Start();
try
{
Task.WhenAny(RunAsync()).GetAwaiter().GetResult();
}
catch (TimeoutException)
{
Console.WriteLine("Timed out");
}
Console.WriteLine("Elapsed: " + sw.Elapsed);
Console.WriteLine("Press Enter to exit");
Console.ReadLine();
}
private static async Task RunAsync()
{
await Observable.StartAsync(async ct =>
{
for (int i = 0; i < 10; ++i)
{
await Task.Delay(500, ct);
Console.WriteLine("Inside " + i);
}
return Unit.Default;
}).Timeout(TimeSpan.FromMilliseconds(1000));
}
}
Running wyprowadza:
Inside 0
Inside 1
Elapsed: 00:00:01.1723818
Press Enter to exit
Uwaga, nie Timed out wiadomość.
Teraz, jeśli mogę wymienić Task.WhenAny
z Task.WhenAll
tutaj jest to, co mam:
Inside 0
Inside 1
Timed out
Elapsed: 00:00:01.1362188
Press Enter to exit
Uwaga obecność Timed out komunikat ten czas.
A jeśli usunąć Task.WhenAll
opakowanie w ogóle i nazywają RunAsync
bezpośrednio:
Inside 0
Inside 1
Timed out
Elapsed: 00:00:01.1267617
Press Enter to exit
Timed out wiadomość jest tam, jak oczekiwano.
Więc jaka jest umowa z Task.WhenAny
? To oczywiście przerywa metodę asynchroniczną, ale gdzie jest TimeoutException
?
Dlaczego używasz '.Task.GetAwaiter() .GetResult() ', po pierwsze jest to równoważne' Task.Result', a po drugie możesz być zjedzony przez grue. – Aron
@Aron To nie jest odpowiednik. Zgłasza faktyczny wyjątek. Ale tak, nadal blokuje i może prowadzić do zakleszczeń. – i3arnon
[Task.getAwaiter()] (https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.getawaiter (v = vs.110) .aspx): 'Ta metoda jest przeznaczona do użytku kompilatora, a nie do użycia w kodzie aplikacji. " – sstan