多线程编程(1)
1.使用thread 实例
2.使用delegate ,BeginInvoke
多线程的问题:
1。线程间操作无效: 从不是创建控件“XXXXX”的线程访问它。
answer:
"There are four methods on a control that are safe to call from any thread: Invoke, BeginInvoke, EndInvoke, and CreateGraphics.
For all other method calls, you should use one of the invoke methods to marshal the call to the control's thread."
this.InvokeRequired : which returns true if the calling thread needs to pass control to the UI thread before calling a method on the control.
Control.Invoke will block until the UI thread has processed the request: that is, until Control.Invoke has put a message on the UI thread's message queue and has waited for it to be processed like any other message (except that the delegate's method is called instead of an event handler). Because Invoke takes a Delegate argument, which is the base class for all delegates, it can form a call to any method, using the optional array of objects as arguments and returning an object as the return value for the called method.
Synchronous Callbacks 代码示例
private void btnStart_Click(object sender, EventArgs e)
{
//Thread thread = new Thread(new ThreadStart(Fill));
//thread.Start();
ListBoxStartDelegate startDelegate = new ListBoxStartDelegate(Fill);
startDelegate.BeginInvoke(null,null);
}
private void Fill()
{
ListBoxFillDelegate fillDelegate = new ListBoxFillDelegate(FillList);
int i = 0;
while (true)
{
i++;
this.Invoke(fillDelegate, new object[] { i.ToString()});
}
}
private void FillList(string message)
{
listBox1.Items.Insert(0, message);
//Debug.Assert(this.InvokeRequired==true);
}
1.在start 方法中,创建一个新的线程,用于执行fill操作。
2.在fill方法中 由于要定时的处理 主线程(UI thread)中的control,所以在当前的线程中创建一个新的delegate,代理的方法为filllist,并由主线程通过invoke方法执行这个delegate.
1-2.Now the UI thread uses a delegate, calling Delegate.BeginInvoke to spawn a worker thread, and the worker thread uses Control.Invoke to pass control back to the UI thread when the progress controls need updating
对象--暴露一个event--使用delegate注册监听者的eventHandler, 当 event 触发时,把eventArgs 多播到eventHandler.
之所以可以这样是因为,delegate 可以在任意线程调用,可以延迟方法的执行。
Asynchronous Callbacks 代码示例
由于在同步的程序中,work thread use invoke method ,so work thread have to wait for the ui thread, but we didn’t need any output or return value,so we can
use beginInvoke .
so what’s different from beginInvoke and Invoke?
BeginInvoke 返回 IAsyncResult ,which provides access to the current status of the request and allows the worker thread to harvest any results. Because there are no results to harvest, there's no need to worry about the IAsyncResult or ever calling EndInvoke.
涉及到调用主线程的方法,可以修改为下面这样
--------------------------------old--------------------------------
private void Fill()
{
ListBoxFillDelegate fillDelegate = new ListBoxFillDelegate(FillList);
int i = 0;
while (true)
{
i++;
this.Invoke(fillDelegate, new object[] { i.ToString()});
}
}
private void FillList(string message)
{
listBox1.Items.Insert(0, message);
//Debug.Assert(this.InvokeRequired==true);
}
--------------------------------new--------------------------------
private void Fill()
{// Make sure we're on the UI thread
if( this.InvokeRequired == false )
{
listBox1.Items.Insert(0, message);
}
else
{
ListBoxFillDelegate fillDelegate = new ListBoxFillDelegate(Fill);
this.BeginInvoke(null,null);
}
}
为了使用状态机制,控制进程,需要使用lock防止race conditions