在使用Dotnetfx2.0开发WinForm程序时,经常需要使用后台线程来进行运算,并把运算的过程数据,结果数据等信息更新显示到窗口中。由于窗体线程和工作线程不是一个线程,我们不能在工作线程中直接设置窗体中控件的属性,而需要使用Control.Invoke(Delegate del,...)来间接调用。其实,可以使用一个匿名函数很简单的调用。
按照MSDN上的标准作法,如果有一个函数:
void WriteMessage(string msg)
{
this.tbMsg.Text += msg;
}
{
this.tbMsg.Text += msg;
}
要在工作线程函数中调用,需要先声明一个委托:
public delegate void WriteMessageHandle(string);
然后在线程函数中调用:
public void ThreadProc(object obj)
{
..
this.Invoke(new WriteMessageHandle(this.WriteMessag, new object[]{"hello world"}));
..
}
{
..
this.Invoke(new WriteMessageHandle(this.WriteMessag, new object[]{"hello world"}));
..
}
其实,就为了一句: this.tbMsg.Text += msg; 费了多大事呀。 其实,在C# 2.0中, 我们可以很简单:
// 先声明这样一个万用的委托
public delegate void VoidDelegate();
public void ThreadProc(object obj)
{
//这是要输出的消息
string msg = "Hello World";
.
//由于是在工作线程中,我们不用理 this.InvokeRequired,直接调用
//直接使用匿名函数,这样可以使用 msg 局部变量,哈哈 简单吧
this.Invoke(new VoidDelegate(delegate()
{
//这句就是要执行的函数了
this.tbMsg.Text += msg;
//这里还可以调用其它的窗体相关的代码
// EX
// this.tbName.Text = "my name here ";
}));
.
}
public delegate void VoidDelegate();
public void ThreadProc(object obj)
{
//这是要输出的消息
string msg = "Hello World";
.
//由于是在工作线程中,我们不用理 this.InvokeRequired,直接调用
//直接使用匿名函数,这样可以使用 msg 局部变量,哈哈 简单吧
this.Invoke(new VoidDelegate(delegate()
{
//这句就是要执行的函数了
this.tbMsg.Text += msg;
//这里还可以调用其它的窗体相关的代码
// EX
// this.tbName.Text = "my name here ";
}));
.
}
示例2:工作线程中,使用线程池进行工作,这里还有最大并发控制哟(不知道你们如何实现最大并发):
// 先声明这样一个万用的委托
public delegate void VoidDelegate();
public void ThreadProc(object obj)
{
//假设,并发值为 5
Semaphore poolLock = new Semaphore(5, 5);
//假设 this.WorkItems 是需要进行的工作
foreach(WorkItem workItem in this.WorkItems)
{
//闭包
WorkItem item = workItem;
//保确不超过并发最大值
poolLock.WaitOne();
//使用线程池进行执行,示例使用系统线程池
ThreadPool.QueueUserWorkItem(delegate(object arg)
{
try
{
//这是要输出的消息
string msg = item.Message; // "Hello World";
//由于是在工作线程中,我们不用理 this.InvokeRequired,直接调用
//直接使用匿名函数,这样可以使用 msg 局部变量,哈哈 简单吧
this.Invoke(new VoidDelegate(delegate()
{
//这句就是要执行的函数了
this.tbMsg.Text += msg;
//这里还可以调用其它的窗体相关的代码
// EX
// this.tbName.Text = "my name here ";
}));
}
finally
{
//最后进行释放 并发锁
poolLock.Release();
}
});
}
}
public delegate void VoidDelegate();
public void ThreadProc(object obj)
{
//假设,并发值为 5
Semaphore poolLock = new Semaphore(5, 5);
//假设 this.WorkItems 是需要进行的工作
foreach(WorkItem workItem in this.WorkItems)
{
//闭包
WorkItem item = workItem;
//保确不超过并发最大值
poolLock.WaitOne();
//使用线程池进行执行,示例使用系统线程池
ThreadPool.QueueUserWorkItem(delegate(object arg)
{
try
{
//这是要输出的消息
string msg = item.Message; // "Hello World";
//由于是在工作线程中,我们不用理 this.InvokeRequired,直接调用
//直接使用匿名函数,这样可以使用 msg 局部变量,哈哈 简单吧
this.Invoke(new VoidDelegate(delegate()
{
//这句就是要执行的函数了
this.tbMsg.Text += msg;
//这里还可以调用其它的窗体相关的代码
// EX
// this.tbName.Text = "my name here ";
}));
}
finally
{
//最后进行释放 并发锁
poolLock.Release();
}
});
}
}