2012-11-08 14 views
9

Mam następujący kod w C#, VS2012, WPF 4.5. Oczekuję, że .ContinueWith zostanie wykonane po zakończeniu zadania (to jest cały cel kontynuacji, prawda?).. Kontynuacja rozpoczyna się przed zakończeniem zadania

Powinno to skutkować wartością 2 w finalResult.

int myTestInt = 0; 

Task task = Task.Factory.StartNew(async() => 
{ 
    myTestInt = 1; 
    await Task.Delay(TimeSpan.FromSeconds(6)); 
    myTestInt = 2; 

}).ContinueWith(_ => 
    { 
     int finalResult = myTestInt; 
    }); 

W rzeczywistości finalResult ma przypisaną wartość 1. Wygląda na to, że kontynuacja została już rozpoczęta na oświadczeniu await.

Czy to jest zamierzone zachowanie? Czy coś mi umyka? Czy nie mogę polegać na ContinueWith, aby rozpocząć po zakończeniu zadania?

Aktualizacja:

odpowiedź Justina właśnie zainspirowało mnie, aby sprawdzić, co następuje:

int myTestInt = 0; 
Task task=Task.Factory.StartNew(async() => 
{ 
    myTestInt = 1; 
    await Task.Delay(TimeSpan.FromSeconds(6)); 
    myTestInt = 2; 
}); 

task.Wait(); 
int result2 = myTestInt; 

finalResult jest nadal ustawiony na 1. Czy nie ma sposobu, aby wiarygodnie czekać na zadania, które zawiera await s, aby zakończyć ?

+4

Myślę, że powinieneś wywołać 'Task.Delay' bezpośrednio - nie używając słowa kluczowego' await'. –

+2

Zauważysz, że '_' jest w rzeczywistości' Zadanie ', które w pełni obsługuje to, co Justin mówi ... –

+0

W rzeczywistości przy użyciu Task.Delay (6) spowoduje oczekiwany wynik, ale nie będzie czekać 6 sekund . Myślę, że usunięcie całej linii byłoby prawie takie samo. –

Odpowiedz

10

Gdy zdać async delegata do Task.Factory.StartNew, zwrócony Task stanowi jedynie pierwszą część tego delegata (Aż do chwili jego await coś, co nie jest już zakończone).

Jeśli jednak przekażesz delegata async do nowej metody Task.Run (która została dołączona z tego powodu), zwrócony Task reprezentuje całego delegata. Więc możesz użyć ContinueWith zgodnie z oczekiwaniami. (Chociaż await jest zwykle lepszym rozwiązaniem niż ContinueWith).

Aby uzyskać więcej informacji na temat StartNew vs Run, patrz Stephen Toub's post on the topic.

+0

Połączony post bardzo wyraźnie. Dziękuję Ci!! –

4

Oczekiwanie natychmiast zwróci sterowanie do funkcji wywołującej, która w tym przypadku jest początkiem zadania. Oznacza to, że zadanie następnie zakończy i wykona ContinueWith. Jeśli naprawdę chcesz, aby zadanie zostało wykonane przed ContinueWith, nie czekaj na Task.Delay.

+0

Myślę, że masz rację - czekanie oznacza bieżące zadanie jako zakończone. Chociaż tak nie jest (przynajmniej nie z semantycznego punktu widzenia). Oczekiwanie jest podstawowym elementem całego oprogramowania, co oznacza, że ​​już nigdy nie będziemy polegać na Continuewith. Nie sądzisz, że to błąd? –

-1

Widziałem to w MSDN: :-)

public async void button1_Click(object sender, EventArgs e) 
{ 
    pictureBox1.Image = await Task.Run(async() => 
    { 
     using(Bitmap bmp1 = await DownloadFirstImageAsync()) 
     using(Bitmap bmp2 = await DownloadSecondImageAsync()) 
     return Mashup(bmp1, bmp2); 
    }); 
} 

Więc nie zapomni "asynchronicznie()" !!!

+0

Jego kod ma 'asynchroniczne' jego problem polega na tym, że używa' TaskFactory', który nie ma przeciążenia, które ma postać 'Func ' lub 'Func >' której 'Task.Run' posiada. –

Powiązane problemy