线程点滴
一、跨线程访问控件
跨线程访问控件,定义一个委托,委托指向的是该方法,然后使用Invoke方法调用这个委托。
代码
private Thread thdSample;
privatedelegatevoid SetReceiveTextEventHandler();
privatevoid btnReceive_Click(object sender, EventArgs e)
{
thdSample =new Thread(new ThreadStart(thdSampleRun));
thdSample.Start();
}
publicvoid thdSampleRun()
{
SetReceiveText();
}
publicvoid SetReceiveText()
{
if (this.InvokeRequired)
{
SetReceiveTextEventHandler handler =
new SetReceiveTextEventHandler(SetReceiveText);
this.Invoke(handler, newobject[] { });
}
else
{
lock (rtbReceive)
{
rtbReceive.AppendText("跨线程调用主线程控件...");
rtbReceive.AppendText("\n");
}
thdSample.Abort();
}
}
privatedelegatevoid SetReceiveTextEventHandler();
privatevoid btnReceive_Click(object sender, EventArgs e)
{
thdSample =new Thread(new ThreadStart(thdSampleRun));
thdSample.Start();
}
publicvoid thdSampleRun()
{
SetReceiveText();
}
publicvoid SetReceiveText()
{
if (this.InvokeRequired)
{
SetReceiveTextEventHandler handler =
new SetReceiveTextEventHandler(SetReceiveText);
this.Invoke(handler, newobject[] { });
}
else
{
lock (rtbReceive)
{
rtbReceive.AppendText("跨线程调用主线程控件...");
rtbReceive.AppendText("\n");
}
thdSample.Abort();
}
}
lock期间:
1.其他线程无法访问rtbReceive控件。
2.其他线程无法执行lock里面代码块。
二、异步委托
异步委托的使用:
代码
privatedelegatedouble RunAsyncEventHandler(double douA, double douB);
privatedelegatevoid SetSendTextEventHandler(string strText);
private RunAsyncEventHandler asyncHandler;
privatevoid btnSend_Click(object sender, EventArgs e)
{
asyncHandler =new RunAsyncEventHandler(RunAsync);
asyncHandler.BeginInvoke(5d, 3d,
new AsyncCallback(GetAsyncResult), null);
}
publicdouble RunAsync(double douA, double douB)
{
Thread.Sleep(3000);
return douA + douB;
}
publicvoid GetAsyncResult(IAsyncResult result)
{
double douResult = asyncHandler.EndInvoke(result);
//1.第一种方法
this.Invoke(new SetSendTextEventHandler(rtbSend.AppendText),
newobject[] { douResult.ToString() +"\n" });
//2.第二种方法
SetSendText(douResult.ToString());
}
publicvoid SetSendText(string strText)
{
if (this.InvokeRequired)
{
SetSendTextEventHandler handler =
new SetSendTextEventHandler(SetSendText);
this.Invoke(handler, newobject[] { strText });
}
else
{
lock (rtbSend)
{
rtbSend.AppendText(strText);
rtbSend.AppendText("\n");
}
}
}
privatedelegatevoid SetSendTextEventHandler(string strText);
private RunAsyncEventHandler asyncHandler;
privatevoid btnSend_Click(object sender, EventArgs e)
{
asyncHandler =new RunAsyncEventHandler(RunAsync);
asyncHandler.BeginInvoke(5d, 3d,
new AsyncCallback(GetAsyncResult), null);
}
publicdouble RunAsync(double douA, double douB)
{
Thread.Sleep(3000);
return douA + douB;
}
publicvoid GetAsyncResult(IAsyncResult result)
{
double douResult = asyncHandler.EndInvoke(result);
//1.第一种方法
this.Invoke(new SetSendTextEventHandler(rtbSend.AppendText),
newobject[] { douResult.ToString() +"\n" });
//2.第二种方法
SetSendText(douResult.ToString());
}
publicvoid SetSendText(string strText)
{
if (this.InvokeRequired)
{
SetSendTextEventHandler handler =
new SetSendTextEventHandler(SetSendText);
this.Invoke(handler, newobject[] { strText });
}
else
{
lock (rtbSend)
{
rtbSend.AppendText(strText);
rtbSend.AppendText("\n");
}
}
}
在执行RunAsync方法时候,窗体仍然可以继续进行其他操作,异步委托创建的线程是位于线程池中,若要调用控件则需要使用Invoke方法进行调用。
三、BackgroundWorker
使用注意(来自MSDN):
您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
BackgroundWorker 事件不跨 AppDomain 边界进行封送处理。请不要使用 BackgroundWorker 组件在多个 AppDomain 中执行多线程操作。
代码
privatedelegatevoid DoWorkerEventHandler(string strText);
privatevoid btnThdWorker_Click(object sender, EventArgs e)
{
BackgroundWorker thdWorker =new BackgroundWorker();
thdWorker.DoWork +=new DoWorkEventHandler(thdWorker_DoWork);
thdWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(thdWorker_RunWorkerCompleted);
thdWorker.RunWorkerAsync();
}
//线程工作事件
publicvoid thdWorker_DoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(4000);
//第一种
this.Invoke(new DoWorkerEventHandler(this.rtbSend.AppendText),
newobject[] { "BackgroundWorker使用" });
//第二种
SetWorkerText("BackgroundWorker使用");
}
//线程工作完毕事件
publicvoid thdWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
rtbSend.AppendText("线程工作完毕事件封送回控件线程...");
}
publicvoid SetWorkerText(string strText)
{
if (this.InvokeRequired)
{
DoWorkerEventHandler handler =
new DoWorkerEventHandler(SetWorkerText);
this.Invoke(handler, newobject[] { strText });
}
else
{
lock (this.rtbSend)
{
rtbSend.AppendText(strText);
}
}
}
privatevoid btnThdWorker_Click(object sender, EventArgs e)
{
BackgroundWorker thdWorker =new BackgroundWorker();
thdWorker.DoWork +=new DoWorkEventHandler(thdWorker_DoWork);
thdWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(thdWorker_RunWorkerCompleted);
thdWorker.RunWorkerAsync();
}
//线程工作事件
publicvoid thdWorker_DoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(4000);
//第一种
this.Invoke(new DoWorkerEventHandler(this.rtbSend.AppendText),
newobject[] { "BackgroundWorker使用" });
//第二种
SetWorkerText("BackgroundWorker使用");
}
//线程工作完毕事件
publicvoid thdWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
rtbSend.AppendText("线程工作完毕事件封送回控件线程...");
}
publicvoid SetWorkerText(string strText)
{
if (this.InvokeRequired)
{
DoWorkerEventHandler handler =
new DoWorkerEventHandler(SetWorkerText);
this.Invoke(handler, newobject[] { strText });
}
else
{
lock (this.rtbSend)
{
rtbSend.AppendText(strText);
}
}
}
四、ThreadPool
代码
privatedelegatevoid RunThreadPoolEventHandler(string strText);
privatevoid btnThdPool_Click(object sender, EventArgs e)
{
string strText ="线程池的使用";
ThreadPool.QueueUserWorkItem(new WaitCallback(RunThreadPool), strText);
}
publicvoid RunThreadPool(object obj)
{
Thread.Sleep(2000);
this.Invoke(
new RunThreadPoolEventHandler(rtbReceive.AppendText),
newobject[] { obj.ToString() }
);
}
privatevoid btnThdPool_Click(object sender, EventArgs e)
{
string strText ="线程池的使用";
ThreadPool.QueueUserWorkItem(new WaitCallback(RunThreadPool), strText);
}
publicvoid RunThreadPool(object obj)
{
Thread.Sleep(2000);
this.Invoke(
new RunThreadPoolEventHandler(rtbReceive.AppendText),
newobject[] { obj.ToString() }
);
}
若有疑问或不正之处,欢迎提出指正和讨论。