2012-10-29 50 views
2

我一直在閱讀.NET 4.5中引入的異步/等待語法,並瞭解它。.Net 4.5和Task.Yield與Task.Delay作爲DoEvents的替代方案?使用哪個?

我發現簡單的示例,其中Task.Yield是要去的方式而不是Application.DoEvents。我試圖將樣品(填空)之一

代碼Form1上用1個按鈕:

public async void button1_Click(object sender, EventArgs e) { 
    var list = new List<int>(); 
    for (int i = 0; i < 10000; i++) { 
     list.Add(i); 
    } 
    for (int i = 0; i < list.Count; i++) { 
     Process(list[i]); 
     await Task.Yield(); 
     //await Task.Delay(1); 
    } 
} 

public static void Process(int i) { 
    Debug.WriteLine(i); 
} 

但是,運行該代碼時,UI線程被阻塞或我相信它被阻塞,因爲我可以在代碼運行時不要移動窗口。如果我將Task.Yield()註釋掉並改爲使用Task.Delay(1)行,那麼GUI是可以響應的。

所以我誤解了這裏的東西?我知道使用DoEvents等是不好的做法,但我有一些遺留代碼,我負責使用這個,我打算用Yield來代替它,因爲它是最好的選擇。但首先我需要用異步/等待來溫暖。

+0

這是在MSDN Library文章Task.Yield中明確:'出於這個原因,不靠等待Task.Yield();保持界面響應。「# –

+0

好的。糟糕的樣本在網上,然後在misc博客。 – Wolf5

回答

4

async不會神奇地讓你的代碼更好。 Yield不是DoEvents(這是邪惡的)的直接替代。需要一些工作來改變代碼的對齊方式。

只要你不需要UI背景下,你可以把你的事推到線程池:

public async void button1_Click(object sender, EventArgs e) { 
    await Task.Run(() => { 
    var list = new List<int>(); 
    for (int i = 0; i < 10000; i++) { 
     list.Add(i); 
    } 
    for (int i = 0; i < list.Count; i++) { 
     Process(list[i]); 
    } 
    }); 
} 

或者,您也可以考慮使用IProgress<T>分手的UI相關的部分之一或使用Task.Run對於非UI工作:

public async void button1_Click(object sender, EventArgs e) { 
    var list = new List<int>(); 
    await Task.Run(() => { 
    for (int i = 0; i < 10000; i++) { 
     list.Add(i); 
    } 
    }); 

    for (int i = 0; i < list.Count; i++) { 
    await ProcessAsync(list[i]); 
    } 
} 

public static async Task ProcessAsync(int i) { 
    await Task.Run(() => { ... }); // background 
    myUi.Text = i.ToString() + " working"; // ui 
    await Task.Run(() => { ... }); // more background 
    myUi.Text = i.ToString() + " complete"; // ui 
} 
+0

是的。我非常非常異步,用我自己的異步庫(pre .net 4.5)來做。但是當我讀到async/await時發現的示例只顯示了Task.Yield的click事件循環,據說可以屈服於UI線程。但爲了獲得它的感覺而進行測試表明,實際上不起作用。所以網上的示例要麼是錯誤的,要麼是我的代碼出錯了。延遲工作。收益率不。 – Wolf5

+0

yield * *將產生到UI事件循環。但它首先安排自己的延續。因此,無論延續是先執行還是其他UI事件,都取決於事件循環。例如,'GetMessage' [定義從UI循環中檢索的消息的優先級](http://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v = vs.85).aspx ),可能無法在'Yield'上表現出色。 –

+0

所以人們不能相信收益喲行爲正確的方式來取代DoEvents。延遲仍然有效。但延遲比DoEvents更好用嗎? – Wolf5