Re: [問題] Thread被咬住如何解決?

作者: fo40225   2015-07-28 23:10:39
嘗試寫一個比較簡單好理解的版本
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
tabControl1.SelectedIndex = 1;
var task = Task.Run(() =>
{
DateTime DateTime1 = DateTime.Now;
TimeSpan ts1 = new TimeSpan(DateTime1.Ticks);
DateTime DateTime2;
TimeSpan ts2;
TimeSpan ts = new TimeSpan();
while (progressBar1.Value < progressBar1.Maximum)
{
DateTime2 = DateTime.Now;
ts2 = new TimeSpan(DateTime2.Ticks);
ts = ts1.Subtract(ts2).Duration();
this.Invoke((Action)(() =>
progressBar1.Value = Convert.ToInt32((ts.TotalSeconds / 1.5) * 100)));
}
//PASS Color 128,255,128 Green
this.Invoke((Action)(() =>
label1.BackColor = Color.FromArgb(128, 255, 128)));
this.Invoke((Action)(() =>
label1.ForeColor = Color.Green));
MessageBox.Show(ts.TotalSeconds.ToString());
});
await task;
}
}
: 2.為什麼裡面這個async可以直接加上「()」和「=>」這些符號
: 還有它們的作用是什麼?
這是lambda表示式 代表一個匿名函式 如果不使用lambda 另外寫具名方法也可以
請參考
https://msdn.microsoft.com/zh-tw/library/bb397687
: 【2】
: _CurrentContext.Post(new SendOrPostCallback((_) => {...}), null);
: 這段....老實說....有點....超出理解範圍 |||"orz
: 但是連查了MSDN都看不懂它們要怎麼使用 爬Google也幾乎找不到相關資料
: 希望能有詳細一點的解釋還有符號的說明 真是不好意思 OAQ
這個超出新手範圍 你應該要知道的是 在WinForm程式中 非UI執行緒不能更新UI
所以必須將你想要更新UI的方法想辦法傳給UI執行緒
singledream 是將UI執行緒的上下文記起來 然後將更新的方法Post過去
注意看我程式碼紅字的地方 我一樣將一個方法(是一個lambda匿名函式)
傳入this(form1)的Invoke方法 這個方法會在UI執行緒上執行你指定的方法
: 目前可以看得出來的地方是 不會卡住CPU的地方直接寫出來
: 可能會咬死的地方則是用async跟await製造出另一個thread
: 雖然直接看完成的程式可以得到這個結論
: 但是裡面的語法跟設計期間的邏輯卻還是有點不懂
: 換句話說就是如果要從零開始重新coding的話很可能會想不到該怎麼做
async await 背後是 ThreadPool 不一定會有新的執行緒
產生一個新的Task就是把你的方法放到排程裡
runtime會調度ThreadPool幫你把Task完成
簡單的想法就是把await看成是會存檔的return
當Task完成後 會接著await之後繼續做
不一定是原來的執行緒 只有winform會是同一個
因為背後偷偷幫你用了SynchronizationContext
可以試著在winform與console中執行下面的範例
private async void button1_Click(object sender, EventArgs e)
{
M1();
await Task.Delay(1000);
M2();
}
private void M1()
{
MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
}
private void M2()
{
MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
}
console
internal class Program
{
static void Main(string[] args)
{
Program.MainAsync().Wait();
}
private static async Task MainAsync()
{
Program.M1();
await Task.Delay(1000);
Program.M2();
}
private static void M1()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
}
private static void M2()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
}
}
async await 更多請參考
https://msdn.microsoft.com/zh-tw/library/hh191443
由於 async await 是基於Task的 最好先搞懂TPL 會比較好懂
https://msdn.microsoft.com/zh-tw/library/dd537609
: 另外 推文也有提到說「一直去頻繁更新UI也是不好的」
: 那應該怎麼做才對?
: 除了不斷地去更新它 我實在想不到什麼比較好的辦法 |||"orz
可以設定Timer 由UI去問進度 或是Task一段時間回報進度再更新UI都可以
※ 引述《pthuang (◢曉筱◤)》之銘言:
: 希望有人或是fo40225可以幫我解個惑 謝謝 m(_ _)m
作者: singledream (魚大頭)   2015-07-31 00:36:00
有些解釋好像比較讓人淺顯易懂,謝謝版友分享

Links booklink

Contact Us: admin [ a t ] ucptt.com