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收到信号。

 

  四个按钮:开始、暂停、继续、退出

 

 

ExpandedBlockStart.gif 代码
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();
                }
            }
        }
       

    }
}

 

 

  

 

 

 

 

 


 

转载于:https://www.cnblogs.com/fangzheng/archive/2010/06/07/1750205.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值