航班数据获取系统的使命是:在每天的指定时刻去网站抓取数据。当系统开始运行后,将无人看管。因此系统的关键在于两点:一是由于数据量巨大,需要开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();
}
}
}
}
}