ManualResetEvent在多线程循环中的应用
航班数据获取系统的使命是:在每天的指定时刻去网站抓取数据。当系统开始运行后,将无人看管。因此系统的关键在于两点:一是由于数据量巨大,需要开10个线程去获取数据。二是线程要循环获取数据,保证每一天的指定时刻都会开始获取数据。关键点1在文章lock在多线程中的应用已经完成。故本篇主要完成关键点2。之前在线程的循环问题上徘徊良久,不得其中奥妙。如今,将自己所思所得,与尔等分享,以期共同进步。
碰到的问题有这么2个:
1、当线程start()之后,便不能再start()。
解决方法:等线程运行完成,自行结束,然后重新新建线程。
2、使用suspend()、resume(),被.net告知,已过时,请用信号量机制。不得已,学习ManualResetEvent()。发现,确实能很方便地解决问题,简单极了。
首先,明确概念:ManualResetEvent是线程同步事件,用来通知1个或多个线程 。
其次,明确三个重要方法:
1)Set(),将事件状态设为终止,允许1个或多个线程继续。
2)ReSet(),将事件状态设为非终止,导致1个或多个线程阴止。
3)WaitOne(),阻止当前线程,直到当前ManualResetEvent收到信号。
四个按钮:开始、暂停、继续、退出
代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OracleClient;
using System.Net;
using System.Threading;
using System.Collections;
namespace DataManage
{
public partial class FlightGet : Form
{
public DataTable dt;
public string sConnectionString = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"].ToString();
public Thread tGet;//获取所有AIRLINE的线程
public Thread tCompare;//指定时间的线程
public Thread tGetHtml1;//获取网页线程1
public Thread tGetHtml2;//获取网页线程2
public Thread tGetHtml3;//获取网页线程3
public Thread tGetHtml4;//获取网页线程4
public Thread tGetHtml5;//获取网页线程5
public Thread tGetHtml6;//获取网页线程6
public Thread tGetHtml7;//获取网页线程7
public Thread tGetHtml8;//获取网页线程8
public Thread tGetHtml9;//获取网页线程9
public Thread tGetHtml10;//获取网页线程10
public Hashtable parm;
public string targetURL;
public int currcount = 0;
DataRow newrow;
System.Object obj = new object();//用于lock的对象
object objCmd = new object();
public delegate void AddTxt();//定义UI更新代理
public delegate void dTxt(int iNum);//更新进度条及航线数量代理
public delegate void dTime(string sTime);//更新时间的代理
public delegate void dSetButton(bool sTag);//更新按钮的可用
bool bPauseTag = false;//暂停标志
public ManualResetEvent mBegin = new ManualResetEvent(false);
public FlightGet()
{
InitializeComponent();
SetButtonStart(true);
SetButtonPause(false);
SetButtonContinue(false);
}
//当前航班
public void Writting(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(Writting), iNum);
}
else
{
this.tb_flight1.Text = iNum.ToString();
}
}
//剩余航班
public void LeaveFlight(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(LeaveFlight), iNum);
}
else
{
this.tb_flight2.Text = iNum.ToString();
}
}
//所用时间
public void UseTime(string sTime)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTime(UseTime), sTime);
}
else
{
this.tb_time1.Text = sTime;
}
}
//剩余时间
public void LeaveTime(string sTime)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTime(LeaveTime), sTime);
}
else
{
this.tb_time2.Text = sTime;
}
}
//进度条过程值
public void SetBar(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(SetBar), iNum);
}
else
{
this.bar.Value = iNum;
}
}
//进度条开始值
public void SetBarMin(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(SetBarMin), iNum);
}
else
{
this.bar.Minimum = iNum;
}
}
//进度条最大值
public void SetBarMax(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(SetBarMax), iNum);
}
else
{
this.bar.Maximum = iNum;
}
}
//进度
public void SetRate(string sTime)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTime(SetRate), sTime);
}
else
{
this.l_rate.Text = sTime;
}
}
//开始按钮
public void SetButtonStart(bool sTag)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dSetButton(SetButtonStart), sTag);
}
else
{
this.btn_start.Enabled = sTag;
}
}
//暂停按钮
public void SetButtonPause(bool sTag)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dSetButton(SetButtonPause), sTag);
}
else
{
this.btn_pause.Enabled = sTag;
}
}
//继续按钮
public void SetButtonContinue(bool sTag)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dSetButton(SetButtonContinue), sTag);
}
else
{
this.btn_continue.Enabled = sTag;
}
}
private void btn_start_Click(object sender, EventArgs e)
{
SetButtonStart(false);
SetButtonPause(false);
SetButtonContinue(false);
tCompare = new Thread(new ThreadStart(compare));
tCompare.IsBackground = true;
tCompare.Start();
}
//暂停
private void btn_pause_Click(object sender, EventArgs e)
{
SetButtonPause(false);
SetButtonContinue(true);
mBegin.Reset();//阻止所有线程
}
//继续
private void btn_continue_Click(object sender, EventArgs e)
{
SetButtonPause(true);
SetButtonContinue(false);
mBegin.Set();//继续所有线程
}
//退出
private void btn_exit_Click(object sender, EventArgs e)
{
this.Close();
}
//比对时间,无穷地比对
public void compare()
{
while (1 == 1)
{
Application.DoEvents();
System.DateTime currentTime = new System.DateTime();
currentTime = System.DateTime.Now;
int iHour = currentTime.Hour;//当前 时
int iMinute = currentTime.Minute;//当前 分
int iSecond = currentTime.Second;// 当前 秒
int xHour = int.Parse(tb_hour.Text);//设定 时
int xMinute = int.Parse(tb_minute.Text);//设定 分
int xSecond = int.Parse(tb_second.Text);//设定 秒
if (iHour == xHour && iMinute == xMinute && iSecond == xSecond)//到达指定时间,启动10个线程
{
Thread.Sleep(2000);
currcount = 0;//从第一行开始获取
SetButtonContinue(true);
SetButtonPause(true);
tGetHtml1 = new Thread(new ThreadStart(GetHtml));
tGetHtml1.IsBackground = true;
tGetHtml1.Start();
tGetHtml2 = new Thread(new ThreadStart(GetHtml));
tGetHtml2.IsBackground = true;
tGetHtml2.Start();
tGetHtml3 = new Thread(new ThreadStart(GetHtml));
tGetHtml3.IsBackground = true;
tGetHtml3.Start();
tGetHtml4 = new Thread(new ThreadStart(GetHtml));
tGetHtml4.IsBackground = true;
tGetHtml4.Start();
tGetHtml5 = new Thread(new ThreadStart(GetHtml));
tGetHtml5.IsBackground = true;
tGetHtml5.Start();
tGetHtml6 = new Thread(new ThreadStart(GetHtml));
tGetHtml6.IsBackground = true;
tGetHtml6.Start();
tGetHtml7 = new Thread(new ThreadStart(GetHtml));
tGetHtml7.IsBackground = true;
tGetHtml7.Start();
tGetHtml8 = new Thread(new ThreadStart(GetHtml));
tGetHtml8.IsBackground = true;
tGetHtml8.Start();
tGetHtml9 = new Thread(new ThreadStart(GetHtml));
tGetHtml9.IsBackground = true;
tGetHtml9.Start();
tGetHtml10 = new Thread(new ThreadStart(GetHtml));
tGetHtml10.IsBackground = true;
tGetHtml10.Start();
mBegin.Set();//给出信号
}
else
{
Thread.Sleep(1000);
continue;
}
}
}
public void GetHtml()
{
mBegin.WaitOne();
int iCountRows = dt.Rows.Count;
bool flag = false;
while (true)
{
mBegin.WaitOne();//为暂停功能而设
lock (obj)
{
if (currcount < iCountRows)
{
newrow = dt.Rows[currcount];
currcount = currcount + 1;
flag = true;
}
else
{
SetButtonPause(false);
SetButtonContinue(false);
flag = false;
}
if (flag == false)
{
break;//跳出while循环,10个线程依次终止
}
}
for (int j = 0; j < int.Parse(tb_dates.Text); j++)
{
mBegin.WaitOne();//为暂停功能而设
//获取网页字符串
WebClient wc = new WebClient();
byte[] myDataBuffer = wc.DownloadData(targetURL);
string s = System.Text.ASCIIEncoding.Default.GetString(myDataBuffer);
…………//获取数据
}
}
}
private void FlightGet_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("确定关闭?", "关闭确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
{
e.Cancel = true;
}
else
{
if (tCompare.IsAlive)
{
tCompare.Abort();
}
if (tGetHtml1!=null && tGetHtml1.IsAlive)
{
tGetHtml1.Abort();
}
if (tGetHtml2!=null && tGetHtml2.IsAlive)
{
tGetHtml2.Abort();
}
if (tGetHtml3!=null && tGetHtml3.IsAlive)
{
tGetHtml3.Abort();
}
if (tGetHtml4!=null && tGetHtml4.IsAlive)
{
tGetHtml4.Abort();
}
if (tGetHtml5!=null && tGetHtml5.IsAlive)
{
tGetHtml5.Abort();
}
if (tGetHtml6!=null&& tGetHtml6.IsAlive)
{
tGetHtml6.Abort();
}
if (tGetHtml7 !=null && tGetHtml7.IsAlive)
{
tGetHtml7.Abort();
}
if (tGetHtml8 !=null && tGetHtml8.IsAlive)
{
tGetHtml8.Abort();
}
if (tGetHtml9!=null && tGetHtml9.IsAlive)
{
tGetHtml9.Abort();
}
if (tGetHtml10 !=null && tGetHtml10.IsAlive)
{
tGetHtml10.Abort();
}
}
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OracleClient;
using System.Net;
using System.Threading;
using System.Collections;
namespace DataManage
{
public partial class FlightGet : Form
{
public DataTable dt;
public string sConnectionString = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"].ToString();
public Thread tGet;//获取所有AIRLINE的线程
public Thread tCompare;//指定时间的线程
public Thread tGetHtml1;//获取网页线程1
public Thread tGetHtml2;//获取网页线程2
public Thread tGetHtml3;//获取网页线程3
public Thread tGetHtml4;//获取网页线程4
public Thread tGetHtml5;//获取网页线程5
public Thread tGetHtml6;//获取网页线程6
public Thread tGetHtml7;//获取网页线程7
public Thread tGetHtml8;//获取网页线程8
public Thread tGetHtml9;//获取网页线程9
public Thread tGetHtml10;//获取网页线程10
public Hashtable parm;
public string targetURL;
public int currcount = 0;
DataRow newrow;
System.Object obj = new object();//用于lock的对象
object objCmd = new object();
public delegate void AddTxt();//定义UI更新代理
public delegate void dTxt(int iNum);//更新进度条及航线数量代理
public delegate void dTime(string sTime);//更新时间的代理
public delegate void dSetButton(bool sTag);//更新按钮的可用
bool bPauseTag = false;//暂停标志
public ManualResetEvent mBegin = new ManualResetEvent(false);
public FlightGet()
{
InitializeComponent();
SetButtonStart(true);
SetButtonPause(false);
SetButtonContinue(false);
}
//当前航班
public void Writting(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(Writting), iNum);
}
else
{
this.tb_flight1.Text = iNum.ToString();
}
}
//剩余航班
public void LeaveFlight(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(LeaveFlight), iNum);
}
else
{
this.tb_flight2.Text = iNum.ToString();
}
}
//所用时间
public void UseTime(string sTime)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTime(UseTime), sTime);
}
else
{
this.tb_time1.Text = sTime;
}
}
//剩余时间
public void LeaveTime(string sTime)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTime(LeaveTime), sTime);
}
else
{
this.tb_time2.Text = sTime;
}
}
//进度条过程值
public void SetBar(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(SetBar), iNum);
}
else
{
this.bar.Value = iNum;
}
}
//进度条开始值
public void SetBarMin(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(SetBarMin), iNum);
}
else
{
this.bar.Minimum = iNum;
}
}
//进度条最大值
public void SetBarMax(int iNum)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTxt(SetBarMax), iNum);
}
else
{
this.bar.Maximum = iNum;
}
}
//进度
public void SetRate(string sTime)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dTime(SetRate), sTime);
}
else
{
this.l_rate.Text = sTime;
}
}
//开始按钮
public void SetButtonStart(bool sTag)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dSetButton(SetButtonStart), sTag);
}
else
{
this.btn_start.Enabled = sTag;
}
}
//暂停按钮
public void SetButtonPause(bool sTag)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dSetButton(SetButtonPause), sTag);
}
else
{
this.btn_pause.Enabled = sTag;
}
}
//继续按钮
public void SetButtonContinue(bool sTag)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dSetButton(SetButtonContinue), sTag);
}
else
{
this.btn_continue.Enabled = sTag;
}
}
private void btn_start_Click(object sender, EventArgs e)
{
SetButtonStart(false);
SetButtonPause(false);
SetButtonContinue(false);
tCompare = new Thread(new ThreadStart(compare));
tCompare.IsBackground = true;
tCompare.Start();
}
//暂停
private void btn_pause_Click(object sender, EventArgs e)
{
SetButtonPause(false);
SetButtonContinue(true);
mBegin.Reset();//阻止所有线程
}
//继续
private void btn_continue_Click(object sender, EventArgs e)
{
SetButtonPause(true);
SetButtonContinue(false);
mBegin.Set();//继续所有线程
}
//退出
private void btn_exit_Click(object sender, EventArgs e)
{
this.Close();
}
//比对时间,无穷地比对
public void compare()
{
while (1 == 1)
{
Application.DoEvents();
System.DateTime currentTime = new System.DateTime();
currentTime = System.DateTime.Now;
int iHour = currentTime.Hour;//当前 时
int iMinute = currentTime.Minute;//当前 分
int iSecond = currentTime.Second;// 当前 秒
int xHour = int.Parse(tb_hour.Text);//设定 时
int xMinute = int.Parse(tb_minute.Text);//设定 分
int xSecond = int.Parse(tb_second.Text);//设定 秒
if (iHour == xHour && iMinute == xMinute && iSecond == xSecond)//到达指定时间,启动10个线程
{
Thread.Sleep(2000);
currcount = 0;//从第一行开始获取
SetButtonContinue(true);
SetButtonPause(true);
tGetHtml1 = new Thread(new ThreadStart(GetHtml));
tGetHtml1.IsBackground = true;
tGetHtml1.Start();
tGetHtml2 = new Thread(new ThreadStart(GetHtml));
tGetHtml2.IsBackground = true;
tGetHtml2.Start();
tGetHtml3 = new Thread(new ThreadStart(GetHtml));
tGetHtml3.IsBackground = true;
tGetHtml3.Start();
tGetHtml4 = new Thread(new ThreadStart(GetHtml));
tGetHtml4.IsBackground = true;
tGetHtml4.Start();
tGetHtml5 = new Thread(new ThreadStart(GetHtml));
tGetHtml5.IsBackground = true;
tGetHtml5.Start();
tGetHtml6 = new Thread(new ThreadStart(GetHtml));
tGetHtml6.IsBackground = true;
tGetHtml6.Start();
tGetHtml7 = new Thread(new ThreadStart(GetHtml));
tGetHtml7.IsBackground = true;
tGetHtml7.Start();
tGetHtml8 = new Thread(new ThreadStart(GetHtml));
tGetHtml8.IsBackground = true;
tGetHtml8.Start();
tGetHtml9 = new Thread(new ThreadStart(GetHtml));
tGetHtml9.IsBackground = true;
tGetHtml9.Start();
tGetHtml10 = new Thread(new ThreadStart(GetHtml));
tGetHtml10.IsBackground = true;
tGetHtml10.Start();
mBegin.Set();//给出信号
}
else
{
Thread.Sleep(1000);
continue;
}
}
}
public void GetHtml()
{
mBegin.WaitOne();
int iCountRows = dt.Rows.Count;
bool flag = false;
while (true)
{
mBegin.WaitOne();//为暂停功能而设
lock (obj)
{
if (currcount < iCountRows)
{
newrow = dt.Rows[currcount];
currcount = currcount + 1;
flag = true;
}
else
{
SetButtonPause(false);
SetButtonContinue(false);
flag = false;
}
if (flag == false)
{
break;//跳出while循环,10个线程依次终止
}
}
for (int j = 0; j < int.Parse(tb_dates.Text); j++)
{
mBegin.WaitOne();//为暂停功能而设
//获取网页字符串
WebClient wc = new WebClient();
byte[] myDataBuffer = wc.DownloadData(targetURL);
string s = System.Text.ASCIIEncoding.Default.GetString(myDataBuffer);
…………//获取数据
}
}
}
private void FlightGet_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("确定关闭?", "关闭确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
{
e.Cancel = true;
}
else
{
if (tCompare.IsAlive)
{
tCompare.Abort();
}
if (tGetHtml1!=null && tGetHtml1.IsAlive)
{
tGetHtml1.Abort();
}
if (tGetHtml2!=null && tGetHtml2.IsAlive)
{
tGetHtml2.Abort();
}
if (tGetHtml3!=null && tGetHtml3.IsAlive)
{
tGetHtml3.Abort();
}
if (tGetHtml4!=null && tGetHtml4.IsAlive)
{
tGetHtml4.Abort();
}
if (tGetHtml5!=null && tGetHtml5.IsAlive)
{
tGetHtml5.Abort();
}
if (tGetHtml6!=null&& tGetHtml6.IsAlive)
{
tGetHtml6.Abort();
}
if (tGetHtml7 !=null && tGetHtml7.IsAlive)
{
tGetHtml7.Abort();
}
if (tGetHtml8 !=null && tGetHtml8.IsAlive)
{
tGetHtml8.Abort();
}
if (tGetHtml9!=null && tGetHtml9.IsAlive)
{
tGetHtml9.Abort();
}
if (tGetHtml10 !=null && tGetHtml10.IsAlive)
{
tGetHtml10.Abort();
}
}
}
}
}
posted on 2010-06-07 13:14 WildFlower 阅读(1341) 评论(0) 编辑 收藏 举报