线程点滴

一、跨线程访问控件

跨线程访问控件,定义一个委托,委托指向的是该方法,然后使用Invoke方法调用这个委托。

代码
private Thread thdSample;
private delegate void SetReceiveTextEventHandler();

private void btnReceive_Click( object sender, EventArgs e)
{
thdSample
= new Thread( new ThreadStart(thdSampleRun));
thdSample.Start();
}

public void thdSampleRun()
{
SetReceiveText();
}

public void SetReceiveText()
{
if ( this .InvokeRequired)
{
SetReceiveTextEventHandler handler
=
new SetReceiveTextEventHandler(SetReceiveText);
this .Invoke(handler, new object [] { });
}
else
{
lock (rtbReceive)
{
rtbReceive.AppendText(
" 跨线程调用主线程控件... " );
rtbReceive.AppendText(
" \n " );
}
thdSample.Abort();
}
}

lock期间:

1.其他线程无法访问rtbReceive控件。

2.其他线程无法执行lock里面代码块。

二、异步委托

异步委托的使用:

代码
private delegate double RunAsyncEventHandler( double douA, double douB);
private delegate void SetSendTextEventHandler( string strText);
private RunAsyncEventHandler asyncHandler;

private void btnSend_Click( object sender, EventArgs e)
{
asyncHandler
= new RunAsyncEventHandler(RunAsync);
asyncHandler.BeginInvoke(5d, 3d,
new AsyncCallback(GetAsyncResult), null );
}

public double RunAsync( double douA, double douB)
{
Thread.Sleep(
3000 );
return douA + douB;
}

public void GetAsyncResult(IAsyncResult result)
{
double douResult = asyncHandler.EndInvoke(result);

// 1.第一种方法
this .Invoke( new SetSendTextEventHandler(rtbSend.AppendText),
new object [] { douResult.ToString() + " \n " });

// 2.第二种方法
SetSendText(douResult.ToString());
}

public void SetSendText( string strText)
{
if ( this .InvokeRequired)
{
SetSendTextEventHandler handler
=
new SetSendTextEventHandler(SetSendText);
this .Invoke(handler, new object [] { strText });
}
else
{
lock (rtbSend)
{
rtbSend.AppendText(strText);
rtbSend.AppendText(
" \n " );
}
}
}

在执行RunAsync方法时候,窗体仍然可以继续进行其他操作,异步委托创建的线程是位于线程池中,若要调用控件则需要使用Invoke方法进行调用。

三、BackgroundWorker

使用注意(来自MSDN):

您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
BackgroundWorker 事件不跨 AppDomain 边界进行封送处理。请不要使用 BackgroundWorker 组件在多个 AppDomain 中执行多线程操作。

代码
private delegate void DoWorkerEventHandler( string strText);

private void btnThdWorker_Click( object sender, EventArgs e)
{
BackgroundWorker thdWorker
= new BackgroundWorker();
thdWorker.DoWork
+= new DoWorkEventHandler(thdWorker_DoWork);
thdWorker.RunWorkerCompleted
+=
new RunWorkerCompletedEventHandler(thdWorker_RunWorkerCompleted);
thdWorker.RunWorkerAsync();
}

// 线程工作事件
public void thdWorker_DoWork( object sender, DoWorkEventArgs e)
{
Thread.Sleep(
4000 );

// 第一种
this .Invoke( new DoWorkerEventHandler( this .rtbSend.AppendText),
new object [] { " BackgroundWorker使用 " });

// 第二种
SetWorkerText( " BackgroundWorker使用 " );
}

// 线程工作完毕事件
public void thdWorker_RunWorkerCompleted( object sender,
RunWorkerCompletedEventArgs e)
{
rtbSend.AppendText(
" 线程工作完毕事件封送回控件线程... " );
}

public void SetWorkerText( string strText)
{
if ( this .InvokeRequired)
{
DoWorkerEventHandler handler
=
new DoWorkerEventHandler(SetWorkerText);
this .Invoke(handler, new object [] { strText });
}
else
{
lock ( this .rtbSend)
{
rtbSend.AppendText(strText);
}
}
}

四、ThreadPool

代码
private delegate void RunThreadPoolEventHandler( string strText);

private void btnThdPool_Click( object sender, EventArgs e)
{
string strText = " 线程池的使用 " ;
ThreadPool.QueueUserWorkItem(
new WaitCallback(RunThreadPool), strText);
}

public void RunThreadPool( object obj)
{
Thread.Sleep(
2000 );
this .Invoke(
new RunThreadPoolEventHandler(rtbReceive.AppendText),
new object [] { obj.ToString() }
);
}

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

你可能感兴趣的:(线程)