之前在【C# Threading Finial】裡面已經把目前我所知道 Threading 跟 UI 配合的方法 demo 了一次,
上次同事告訴我說在 .net 4.0 (VS2010) 裡面提供了一個新的方式 Task 來寫 Threading ,
所以我就把上次【C# Threading Finial】裡面的程式拿來改成用 Task 的方式,
測試了一下,的確是簡單了許多,
不過規矩還是一樣,跟 UI 的互動還是得交給主執行緒,
所以還是得用 Invoke 的方式來呼叫,
其實我覺得比較麻煩的還是跟 UI 的互動,其他的倒是還好,
接下來就來看看上次那個程式怎麼修改成 Task 的方式吧!
首先原來的 btnThreadingQuery_Click 就變成下面這樣啦!
改成用 Task.Factory.StartNew 的方式來呼叫 QueryMain()
private void
btnThreadingQuery_Click(object sender, EventArgs e)
{
//ThreadPool.QueueUserWorkItem(new
WaitCallback(QueryMain));
Task.Factory.StartNew(() =>
{
QueryMain();
});
}
然後主程式主要的修改如下:
- 之前 waitHandles 都不要。
- 然後 object param 也不需要。
- 原本用 ThreadPool.QueueUserWorkItem 改成用 Task.Factory.StartNew 。
- 最後 WaitHandle.WaitAll 變成 Task.WaitAll 。
大致上就是這樣,程式碼少了很多變得很簡潔,
整段的程式碼如下:
//private void QueryMain(object param)
private void QueryMain()
{
//waitHandles = new
List<WaitHandle>();
Cursor tmpCursor = this.Cursor;
Label[] labels = { lblThreadingDuration, lblThreadingTable1Count,
lblThreadingTable1Duration, lblThreadingTable2Count,
lblThreadingTable2Duration
};
ResetLabel(labels);
try
{
this.Invoke(new UpdateButtonEnableHandler(UpdateButtonEnable),
new object[] { btnThreadingQuery, false });
this.Invoke(new UpdateFormCursorHandler(UpdateFormCursor),
new object[] { Cursors.WaitCursor });
CalcTime calcTime = new CalcTime();
//waitHandles.Add(new AutoResetEvent(false));
//object param1 = new object[] { "table1",
lblThreadingTable1Count,
//lblThreadingTable1Duration, calcTime};
//lblThreadingTable1Duration, calcTime, waitHandles[waitHandles.Count()-1]};
//ThreadPool.QueueUserWorkItem(
//new WaitCallback(QueryTableByThreading), param1);
var task1 = Task.Factory.StartNew(() =>
{
QueryTableByThreading("table1", lblThreadingTable1Count,
lblThreadingTable1Duration, calcTime);
});
//waitHandles.Add(new AutoResetEvent(false));
//object param2 = new object[] { "table2 ",
lblThreadingTable2Count,
//lblThreadingTable2Duration, calcTime};
//lblThreadingTable2Duration, calcTime,
waitHandles[waitHandles.Count()-1]};
//ThreadPool.QueueUserWorkItem(
//new WaitCallback(QueryTableByThreading), param2);
var task2 = Task.Factory.StartNew(() =>
{
QueryTableByThreading("table2", lblThreadingTable2Count,
lblThreadingTable2Duration, calcTime);
});
//WaitHandle.WaitAll(waitHandles.ToArray());
Task.WaitAll(task1, task2);
//lblThreadingDuration.Text = calcTime.Duration();
this.Invoke(new UpdateLabelTextHandler(UpdateLabelText),
new object[] { lblThreadingDuration, calcTime.Duration() });
}
finally
{
this.Invoke(new UpdateFormCursorHandler(UpdateFormCursor),
new object[] { tmpCursor });
this.Invoke(new UpdateButtonEnableHandler(UpdateButtonEnable),
new object[] { btnThreadingQuery, true });
}
}
然後 QueryTableByThreading 就恢復成原來我們熟悉的寫法,
不用再去解 Object Param 了!程式如下:
//private
void QueryTableByThreading(object param)
private void
QueryTableByThreading(string table, Label count, Label duration, CalcTime ct)
{
//object[] oa = (object[])param;
//string table = oa[0].ToString();
//Label count = (Label)oa[1];
//Label duration = (Label)oa[2];
//CalcTime ct = (CalcTime)oa[3];
//AutoResetEvent are =
(AutoResetEvent)oa[4];
DataTable dt = DBUtility.GetTableFromDB(table);
string time = ct.Duration();
this.Invoke(new UpdateLabelTextHandler(UpdateLabelText),
new object[] { count, dt.Rows.Count.ToString("N") });
this.Invoke(new UpdateLabelTextHandler(UpdateLabelText),
new object[] { duration, time });
//are.Set();
}
不知道甚麼時候可以簡化跟 UI 的互動?
沒有留言:
張貼留言