线程点滴

一、跨线程访问控件

跨线程访问控件,定义一个委托,委托指向的是该方法,然后使用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();
}
}

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");
}
}
}

在执行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);
}
}
}

四、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() }
);
}

若有疑问或不正之处,欢迎提出指正和讨论。 

posted @ 2010-09-01 15:47  iceknp  阅读(319)  评论(0编辑  收藏  举报