ThreadPool.QueueUserWorkItem方法,我用如何調用完成方法每次返回
System.Threading.ThreadPool.QueueUserWorkItem(x => MyMethod(param1, param2, param3, param4, param5));
我希望每次調用的MyMethod完成時調用從主線程下面的方法:
UpdateGui()
{
}
我該怎麼做?
謝謝!
ThreadPool.QueueUserWorkItem方法,我用如何調用完成方法每次返回
System.Threading.ThreadPool.QueueUserWorkItem(x => MyMethod(param1, param2, param3, param4, param5));
我希望每次調用的MyMethod完成時調用從主線程下面的方法:
UpdateGui()
{
}
我該怎麼做?
謝謝!
保留的工作項全球反排隊,一個對象,以保護它:
int runningTasks = 0;
object locker = new object();
每次任務添加增量計數器:
lock(locker) runningTasks++;
System.Threading.ThreadPool.QueueUserWorkItem(x => MyMethod(param1, param2, param3, param4, param5));
在MyMethod
遞減的結束計數器和信號主線程:
lock(locker)
{
runningTasks--;
Monitor.Pulse(locker);
}
在主線程(假設這不是GUI線程!):
lock(locker)
{
while(runningTasks > 0)
{
Monitor.Wait(locker);
UpdateGUI();
}
}
這樣,您還有障礙等待所有未完成的任務完成。
如果您不想等待,只需完全跳過主線程,然後在MyMethod
完成時致電UpdateGUI
將更新轉發到GUI線程。
注意裏面MyMethod
你應該有某種形式的Dispatcher.BeginInvoke
(WPF)或Control.BeginInvoke
(的WinForms),否則你不能安全地更新GUI!
我不明白。 * locker *是一個System.Object,對嗎?是.Pulse和.Wait System.Object的擴展方法?圍繞while循環的鎖定不會阻止MyMethod結束時的鎖定和遞減嗎? – KristoferA 2012-03-31 05:46:28
@ KristoferA-Huagati.com:不,當你在鎖(locker)內調用'Monitor.Wait(locker)'時,鎖會自動釋放,以允許其他線程獲得鎖。此外,'Pulse'和'Wait'是類Monitor的靜態方法,不是'object'的擴展。 – Tudor 2012-03-31 06:47:57
哦,很酷。我不知道,謝謝澄清。 – KristoferA 2012-03-31 12:30:30
假設MyMethod
是一個同步方法中,爲了內QueueUserWorkItem
調用,以使其異步執行,以下方法可以用來:
ThreadPool.QueueUserWorkItem(x =>
{
MyMethod(param1, param2, param3, param4, param5);
UpdateGui();
});
注意,你必須通過更新內部UpdateGui()
GUI元素呼籲Invoke
/BeginInvoke
。
張貼到updategui方法回在線程池方法結束UI線程同步情境中的呼叫......
例子:
private SynchronizationContext _syncContext = null;
public Form1()
{
InitializeComponent();
//get hold of the sync context
_syncContext = SynchronizationContext.Current;
}
private void Form1_Load(object sender, EventArgs e)
{
//queue a call to MyMethod on a threadpool thread
ThreadPool.QueueUserWorkItem(x => MyMethod());
}
private void MyMethod()
{
//do work...
//before exiting, call UpdateGui on the gui thread
_syncContext.Post(
new SendOrPostCallback(
delegate(object state)
{
UpdateGui();
}), null);
}
private void UpdateGui()
{
MessageBox.Show("hello from the GUI thread");
}
我不明白。你能告訴我代碼嗎?謝謝 – Barka 2012-03-29 17:34:25
好的,用代碼示例更新... – KristoferA 2012-03-30 00:52:28
這可以保持客戶端讓清潔該類處理交叉線程切換機制。通過這種方式,GUI以正常方式消耗您的課程。
public partial class Form1 : Form
{
private ExampleController.MyController controller;
public Form1()
{
InitializeComponent();
controller = new ExampleController.MyController((ISynchronizeInvoke) this);
controller.Finished += controller_Finished;
}
void controller_Finished(string returnValue)
{
label1.Text = returnValue;
}
private void button1_Click(object sender, EventArgs e)
{
controller.SubmitTask("Do It");
}
}
GUI表單訂閱了不知道它們覆蓋的線程的類的事件。
public class MyController
{
private ISynchronizeInvoke _syn;
public MyController(ISynchronizeInvoke syn) { _syn = syn; }
public event FinishedTasksHandler Finished;
public void SubmitTask(string someValue)
{
System.Threading.ThreadPool.QueueUserWorkItem(state => submitTask(someValue));
}
private void submitTask(string someValue)
{
someValue = someValue + " " + DateTime.Now.ToString();
System.Threading.Thread.Sleep(5000);
//Finished(someValue); This causes cross threading error if called like this.
if (Finished != null)
{
if (_syn.InvokeRequired)
{
_syn.Invoke(Finished, new object[] { someValue });
}
else
{
Finished(someValue);
}
}
}
}
調用'MyMethod'內的'Control.Invoke'來將委託的執行編組到UI線程中。 – 2012-03-29 17:06:15
爲什麼不使用'Task'和延續? – 2012-03-29 17:15:47
@BrianRasmussen:是的,甚至更好! – 2012-03-29 17:16:45