2014-05-12 81 views
0

有人可以解釋爲什麼SecondTask和加載事件不更新給定此代碼的用戶界面?Task.Run代碼不執行

public Task First() 
{ 
    return Task.Run(
     () => 
     { 

      Task.Delay(4000); 
      Dispatcher.Invoke(() => 
      { 
       Title = "From First()"; 
      }); 
     }); 
} 
public Task Second() 
{ 
    return Task.Run(
     () => 
     { 
      Task.Delay(5000); 
      Dispatcher.Invoke(() => 
      { 
       Title = "From Second()"; 
      }); 
      Task.WaitAny(First()); 
     }); 

} 
    private void ParentWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     Second(); 
     Title = "From Event"; 
    } 

當我運行這段代碼時,由於調用First(),只有窗體標題只改變一次。 沒有別的東西被執行(至少從我所看到的,我可以看到達到的斷點)。 我也嘗試使用Task.WhenAny(First());而不是Task.WaitAny(First());

+0

那麼,你是否設置了一些斷點,然後通過調試器來查看發生了什麼? – mason

+0

已達到斷點,標題永不改變傳遞給First() – user3373870

+0

您在第二次完成後調用First,因此您會看到First –

回答

3

問題是Task.Delay沒有被等待。 Task.Delay是一個異步睡眠,因此它會立即返回,如果您想在延遲之後實際繼續執行,則需要await

那麼在方法Second()中發生的是lambda表達式在後臺線程上執行。當調用Task.Delay(5000)時,由於呼叫未被等待,呼叫立即返回,因此Title設置爲From Second()。然後

public Task Second() 
{ 
    return Task.Run(
     () => 
     { 
      Task.Delay(5000); // need to await here 
      Dispatcher.Invoke(() => 
      { 
       Title = "From Second()"; 
      }); 
      Task.WaitAny(First()); 
     }); 

} 

First()被調用,因爲Task.Delay(4000)也不會被期待已久的,它會立即將TitleFrom First()。所以最終的結果是,你只會看到From First()

public Task First() 
{ 
    return Task.Run(
     () => 
     { 

      Task.Delay(4000); // need to await here 
      Dispatcher.Invoke(() => 
      { 
       Title = "From First()"; 
      }); 
     }); 
} 

您也可能想除非你打算先設置你的標題From Eventawait調用的事件處理程序Second(),然後從Second()結果覆蓋它。

private void ParentWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     Second(); // await this? 
     Title = "From Event"; 
    } 
+0

我認爲你的意思是說Task.Delay(4000).Wait();而不是Task.Delay.Wait(4000); – user3373870

+0

ooops,謝謝 –

+0

感謝您的回答。 – user3373870

1

首先,您需要了解有關任務編程。請閱讀有關my curation的文章。

任務被執行,你只是不要等他們完成。

async-await可以輕鬆完成異步工作,因此您不應該將UI與非UI代碼混合使用。試試這個方法:

public async Task FirstAsync() 
{ 
    await Task.Delay(4000); 
    Title = "From First()"; 
} 

public async Task SecondAsync() 
{ 
    await Task.Delay(5000); 
    Title = "From Second()"; 
    await FirstAsync(); 
} 

private async void ParentWindow_Loaded(object sender, RoutedEventArgs e) 
{ 
    await SecondAsync(); 
    Title = "From Event"; 
} 

這會做你想要什麼,這是更清潔的代碼。