2014-05-12 75 views
0

我有一個按鈕,當我點擊它,我希望它與價值異步與標籤文本

這是我的按鈕

 private async void Button_Click(object sender, RoutedEventArgs e) 
     { 
     await DoItAsync(); 
     } 

,這是DOIT更新UI!

public async Task DoSomethingAsync() 
    { 
     await Task.Run(()=>{ 
      for(int i = 0; i < 2000; i++) 
      { 
       //labelName.Content = i.ToString(); 
       Console.WriteLine(i); 
      } 

     }); 
    } 

,所以如果我運行上面的代碼,請點擊我的按鈕,DoItAysnc被調用,所有的號碼都顯示在控制檯中。

如果我未評論

labelName.Content = i.ToString(); 

我得到一個異常,事實上如下:因爲不同的線程擁有它調用線程不能訪問該對象。

我知道異步並等待不解決線程爲你,但我確實認爲這會工作。我想知道如何讓這個工作,以便在每個i值都更新UI而不會導致UI無響應。

對此的任何好資源也會有幫助。

與往常一樣,各種關於

+0

這是什麼? WPF,WinForms,Windows運行時? – Smeegs

+0

歡迎來到UI線程世界。對於WPF學習Dispatcher,對於Winforms學習Invoke。 –

+2

您需要爲異步/等待做實際工作纔有用。請顯示你實際正在做的事情而不是一個人爲的例子,在你當前的代碼示例中有0個理由使用async/await或線程。 –

回答

8

在這種特殊情況下,似乎所有你正在做的基本上是計算到2000年的標籤一樣快,你所能。這不太可能是您的實際用例。

如果你想被更新多個不同的異步操作的UI(其中該操作,例如,只是在等待一段時間),那麼你可以組織你的代碼如下所示:

private async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    for (int i = 0; i < 2000; i++) 
    { 
     await Task.Delay(TimeSpan.FromSeconds(1)); 
     labelName.Content = i.ToString(); 
    } 
} 

如果你正在做的概念被更新與長時間運行的非UI操作的進度的UI,那麼Progress類被設計來專門處理是:

private async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    Progress<int> progress = new Progress<int>(
     i => labelName.Content = i.ToString()); 
    await Task.Run(() => DoWork(progress)); 
} 
private void DoWork(IProgress<int> progress) 
{ 
    for (int i = 0; i < 2000; i++) 
    { 
     //Do Stuff 
     progress.Report(i); 
    } 
} 

國內首個普遍的選擇是有道理的,如果你C將您的問題分解爲一組小的異步操作,其中UI在每個操作之間更新。如果有一個長的非UI操作不能輕易分解爲更小的操作,則可以採用第二種方法。

0

看看答案here。無論您如何啓動工作線程(Thread.Start,Task.Run,​​BackgroundWorker.RunWorkerAsync),除非在UI線程上運行,否則不會影響UI的更改。

正如@ t-mckeown指出的,解決方案是強制你的方式進入UI線程。你如何做到這一點取決於技術(WFP = Dispatcher,WinForms = InvokeRequired/BeginInvoke)。

+0

'await'捕獲當前同步上下文和marshals回調到該上下文,從而防止開發人員需要顯式編組到UI線程。開始使用這種編程風格是巨大的優勢。 – Servy