通過調用Task.Run你打破了GUI線程(或WPF調度程序)的關聯(的SynchronizationContext),並失去了大部分的異步電動機/等待'善良'。
爲什麼不使用異步無效事件處理程序,並且只是回到每個步驟的SynchronizationContext(GUI Thread/Dispatcher)?
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
while (true)
{
string result = await LoadNextItem();
lbl1.Content = result;
}
}
private static int ir11 = 0;
Task<string> LoadNextItem()
{
await Task.Delay(1000); // placeholder for actual async work
ir11++;
return "aa " + ir11;
}
或者,如果你真的想要的狀態機的「正在進行」操作分開,嘗試傳遞一個IProgress<T>
(默認implement執行。Progress<T>
或專門Progress<string>
應該工作在這種情況下大)。見this article by @Stephen Cleary
他的例子非常接近您在問題中陳述的內容。我在這裏複製它爲了獨立。
public async void StartProcessingButton_Click(object sender, EventArgs e)
{
// The Progress<T> constructor captures our UI context,
// so the lambda will be run on the UI thread.
var progress = new Progress<int>(percent =>
{
textBox1.Text = percent + "%";
});
// DoProcessing is run on the thread pool.
await Task.Run(() => DoProcessing(progress));
textBox1.Text = "Done!";
}
public void DoProcessing(IProgress<int> progress)
{
for (int i = 0; i != 100; ++i)
{
Thread.Sleep(100); // CPU-bound work
if (progress != null)
progress.Report(i);
}
}
編輯:我必須承認,當Progress<T>
是一個很好的抽象,在這種情況下,它只是要掉下來Dispatcher.Invoke爲@Pamparanpa建議。
可能的[如何從C#中的另一個線程更新GUI]重複(http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in- C);具體請參見[本答案](http://stackoverflow.com/a/18033198/3283203)。 – Kilazur