您的位置:首页 > 产品设计 > UI/UE

C#线程类框架,支持消息队列,通过postmessage从UI线程发送消息到工作者线程

2017-01-15 21:33 405 查看
最近期末考试结束了,终于可以干点别的了,以前在MFC上修改师兄的一个桥梁满堂支架实时监控程序,一直没找到很满意的Chart控件来显示监控曲线,听别人说C#里面的控件很丰富而且使用简单,就做了个Demo试了试还真的很好用,就决定把软件从VC6上的MFC平台移植到VS2010的C#平台,由于是实时监控,不添加多线程的话势必会阻塞UI界面的刷新,以前在MFC上用Thread觉得挺简单,没想到来到C#上一看就懵逼了,就仿照着MFC中的Thread使用风格封装了个线程类,反正是能用了,放在这里以备不时之需。

这里类中的End方法与Kill方法的区别就在于,End方法执行后线程并不会马上结束(除非主线程也结束了),而是执行完消息队列中所有剩余消息再结束,Kill方法执行后线程会执行完当前这条消息后马上结束;

Stop方法执行后线程只是暂时不执行消息队列中对应的消息事件,而线程的消息队列是仍在接收消息的,一旦线程恢复,将继续执行消息队列中的所有消息事件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace MDIMonitor_CS
{
public class UserThread
{
private bool end = false;//结束线程标志
private bool kill = false;//终结线程标志
private bool stop = false;//暂停线程标志
private Thread thread = null;//恢复线程标志
private Queue msgQueue = null;//存储消息队列
FrameWin Parent = null;//用于传入其他线程句柄,一般通过线程刷新某个窗口UI,FrameWin是需要控制的窗口类,自行修改
public UserThread(Form parent)
{
Parent = (FrameWin)parent;//强制转换
msgQueue = new Queue();
thread = new Thread(new ThreadStart(Run));//真正定义线程
}
~UserThread()
{
this.End();//析构时结束线程
}
public void PostMessage(int id)//id为传入的消息标识
{
if (end || kill)//如果线程结束或终止,不执行任何动作
return;
if (id > 0)
msgQueue.Enqueue(id);//将post来的消息添加到消息队列
if (stop)
return;//如果线程暂停,将只接受消息,暂不执行,一旦线程恢复,继续执行所接收消息
if (!this.thread.IsAlive)//如果线程未开启,将启动线程
this.thread.Start();
}
public void Start()
{
if (end || kill)//如果线程已被结束或终止,将不执行任何动作
return;
if (!this.thread.IsAlive)//如果线程未开启,将启动线程
thread.Start();
}
public void End()
{
end = true;//如果线程结束,将结束标识设为真,线程将在消息队列中所有消息执行完后终止
Console.WriteLine("结束线程");
}
public void Kill()
{
kill = true;//如果线程终止,将终止标识设为真,线程将不再执行消息队列中剩余消息
Console.WriteLine("终止线程");
}
public void Stop()
{
stop = true;//如果线程暂停,将暂停标识设为真,线程将暂不执行消息队列中剩余消息,
//但是消息队列仍然在接收消息,一旦线程恢复,继续执行所接收消息
Console.WriteLine("暂停线程");
}
public void Resume()
{
stop = false;//如果线程恢复,将恢复标识设为真,线程将继续执行消息队列中剩余消息
Console.WriteLine("恢复线程");
}
private void Run()
{
while (true)
{
if (kill)//如果线程终止,线程函数将立即跳出,消息队列里剩余消息不再执行,此线程结束,无法再开启
break;
if (!stop && msgQueue.Count != 0)//如果线程未被暂停且消息队列中有剩余消息,将顺序执行剩余消息
{
switch (msgQueue.Peek())//获取当前消息队列中消息,并一一比对执行相应的动作
{
case 1:
{
msgFunction_1();//例如消息码为1是,执行msgFunction_1()函数
} break;
case 2:
{
msgFunction_2();//例如消息码为2是,执行msgFunction_2()函数
} break;
}
msgQueue.Dequeue();//比对完当前消息并执行相应动作后,消息队列扔掉当前消息
}
if (msgQueue.Count == 0 && end)//如果线程被结束时当前消息队列中没有消息,将结束此线程
//如果当前消息队列中仍有未执行消息,线程将执行完所有消息后结束
break;
System.Threading.Thread.Sleep(1);//每次循环间隔1ms,我还不知道到底有没有必要
}
}
private void msgFunction_1()//对应消息码为1的时要执行的函数
{
Console.WriteLine("执行消息码1对应事件");
}
private void msgFunction_2()//对应消息码为2的时要执行的函数
{
Console.WriteLine("执行消息码2对应事件");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息