2015-10-04 54 views
1

編輯:Application.DoEvents();這是做到了。在這裏找到:Force GUI update from UI Thread如何使表單延遲顯示

c#,winforms。我想增加一個1的步數,並將這些增量顯示在列表視圖中,以便用戶看到數字向上計數(例如從10到15)。

我有另一個按鈕,點擊時只增加1,並使用相同的顯示()。它工作正常並按預期更新顯示。

我試圖這些代碼(縮短到這裏節省空間):

(1)

for (int i = 0; i < 5; i++) 
{ 
    var t = Task.Run (async() => 
    { 
     myInt++; 
     await Task.Delay(300); 
     display(); //forces screen refresh 
    }); 
} 

(2)

for (int i = 0; i < 5; i++) 
{ 
    var t = Task.Run (() => 
    { 
     myInt++; 
     Task.Delay(300).Wait; 
     display(); 
    }); 
    //t.Wait(); //causes "An unhandled exception of type 'System.AggregateException' occurred in mscorlib.dll" 
} 

(3)

for (int i = 0; i < 5; i++) 
{ 
    myInt++; 
    display(); 
    System.Threading.Thread.Sleep(300); 
} 

(4)

Stopwatch stopwatch = new Stopwatch(); 
for (int i = 0; i < 5; i++) 
{ 
    stopwatch.Restart(); 
    while (true) 
    { 
     if (stopwatch.ElapsedMilliseconds >= 300) 
     { 
      break; 
     } 
    } 
stopwatch.Stop(); 
myInt++; 
display(); 
} 

所有使用該:

private void display() 
{ 
    myListView.Items.Clear(); 
    myListView.Items.Add(new ListViewItem(new[] { myInt })); 
} 

(1)和(2)由5遞增的數量,但顯示不被更新的。它會顯示何時通過其他功能更新顯示。 (3)和(4)將數字增加5,但顯示僅在約1500ms後更新,顯示跳過單個步驟並僅顯示最終結果(例如15)。

任何建議,使其工作?我可以強制刷新display()函數嗎?

爲什麼t.Wait();導致異常? (我發現任務代碼某處網)

編輯:

(5)

private void team_comm_btn_all_Click(object sender, EventArgs e) 
{ 
    for (int i = 0; i < 5; i++) 
    { 
      await Run(i); //error 74 see below 
    } 
} 

private async Task Run(int i) 
{ 
    myInt++; 
    display(); 
    await Task.Delay(300); 
} 

伺機運行(我);給出以下內容: 錯誤74'await'操作符只能在異步方法中使用。考慮使用「異步」修飾符標記此方法,並將其返回類型更改爲「任務」。

只是在執行「Run(i)」而不是提示「await」已丟失......在這種情況下,它編譯並遞增5,沒有任何延遲。

(6)

private void team_comm_btn_all_Click(object sender, EventArgs e) 
{ 
    for (int i = 0; i < 5; i++) 
    { 
     var task = Task.Run(async() => 
     { 
      await Run(i); 
     }); 
    } 
} 

private async Task Run(int i) 
{ 
    myInt++; 
    display(); 
    await Task.Delay(300); 
} 

遞增5,但完全不更新顯示。

+0

http://stackoverflow.com/questions/19028374/accessing-ui-controls-in-task-run-with-async-await- winform –

+0

那個線程並不包括我試過的所有東西,而且我沒有發現任何東西來解決我的問題(請參閱上面的編輯)。儘管它確實提高了我對任務的理解=) – letsdance

+0

是的,沒有投票結束重複,因爲我不確定它是否是同一個問題。自異步發佈之前很久以來,還沒有完成WinForms。事實上,「沒有」發生,然後你突然看到最終值感覺就像沒有處理Windows消息隊列。如果你願意,你會得到這種行爲。有一個循環在正常的事件處理程序中更新UI。不知道具體情況如何適用於你的情況。 –

回答

0

通常你會使用System.Windows.Forms.Timer。但是,只要你理解它,就會使這種事情變得微不足道(仔細閱讀編譯器的警告和錯誤消息)。不久之後,(5)是解決編譯器錯誤的小修改方法。
但讓我們從頭開始。假設你先寫一個正常的同步版本是這樣的(基本上是你的(3))

private void team_comm_btn_all_Click(object sender, EventArgs e) 
{ 
    for (int i = 0; i < 5; i++) 
    { 
     if (i != 0) System.Threading.Thread.Sleep(300); 
     myInt++; 
     display(); 
    } 
} 

正好看到UI沒有更新。所以你決定把它變成異步,這與async/await幫助是簡單與Task.Delay更換Thread.Sleep這樣

private void team_comm_btn_all_Click(object sender, EventArgs e) 
{ 
    for (int i = 0; i < 5; i++) 
    { 
     if (i != 0) await Task.Delay(300); 
     myInt++; 
     display(); 
    } 
} 

但現在失敗,出現以下錯誤

錯誤74編譯「等待'操作符只能在異步方法中使用。考慮使用「異步」修飾符標記此方法,並將其返回類型更改爲「任務」。

該消息足夠清楚。您需要必須async關鍵字標記您的方法。對於將返回類型更改爲Task的其他建議,通常應該考慮這一點,但由於您處於事件處理程序中,即簽名無法更改的方法,因此您可以忽略該部分 - 這就是確切原因允許使用async void

總之,您的最終代碼看起來像這樣

private async void team_comm_btn_all_Click(object sender, EventArgs e) 
{ 
    for (int i = 0; i < 5; i++) 
    { 
     if (i != 0) await Task.Delay(300); 
     myInt++; 
     display(); 
    } 
} 
+0

thx,有時會測試這個。 Application.DoEvents()在這種情況下工作正常,但似乎我遇到類似的麻煩在代碼的其他地方,更優雅的解決方案會更好。 – letsdance