一个c#即时监控小程序

关键词:委托  线程  异步操作  大数据存储过程分页  实时刷新界面数据  声音报警 任务栏提示   动态任务栏图标切换   

需求:启动监控程序后,每隔10秒(可配置多少秒)从后台数据库查询一次,
      查询条件(sql语句可配置),然后返回结果显示和进行判断。
即时插入的数据:(第一列)

本例源码程序

      判断的条件(尽量也可以灵活配置):再返回的数据里面,空号2大于0的多少倍,
      就要间隔1秒再取一次,如果发现还是2的倍数大,那就就报警,
      如果0的倍数大于2很多,就每隔10秒(可配置)查询一次

 



程序界面:


配置:


  


实现代码:
using  System;
using  System.Collections.Generic;
using  System.Configuration;
using  System.Data;
using  System.Drawing;
using  System.IO;
using  System.Runtime.InteropServices;
using  System.Threading;
using  System.Windows.Forms;

namespace  SMMMMonitoring
{
public   partial   class  Form1 : Form
{
private   static   string  strConn  =  ConfigurationManager.AppSettings[ " conStr " ]; ;
private   static   string  strProcedure  =  ConfigurationManager.AppSettings[ " procName " ]; 
private   static   int  pageindex  = Convert.ToInt32( ConfigurationManager.AppSettings[ " pageindex " ]); // 刷新第几页
private   static   int  multiples  =  Convert.ToInt32(ConfigurationManager.AppSettings[ " Multiple " ]); // 报警倍数

StoreProcedure sa 
=   new  StoreProcedure(strProcedure, strConn);

public  Form1()
{
    InitializeComponent();
    
BindDGV();
           
}
private   void  BindDataWithPage( int  Index)
{
    winFormPager1.PageIndex 
=  Index;
  
   string  table  =  ConfigurationManager.AppSettings[ " table " ];
    
string  field  =  ConfigurationManager.AppSettings[ " Field " ];
    
string  orderby  =  ConfigurationManager.AppSettings[ " orderby " ];          
    
string   where   =  ConfigurationManager.AppSettings[ " where " ];
    DataTable dt 
=  sa.ExecuteDataTable(table, field, orderby,  10 , Index,  0 0 where );
    dataGridView1.DataSource 
=  dt;
    winFormPager1.RecordCount 
=  Convert.ToInt32(sa.ExecuteDataTable(table, field, orderby,  10 , Index,  1 0 where ).Rows[ 0 ][ 0 ]);
}

private   void  winFormPager1_PageIndexChanged( object  sender, EventArgs e)
{
    BindDataWithPage(winFormPager1.PageIndex);
}


// 线程间操作无效: 从不是创建控件“dataGridView1”的线程访问它。
// 调用 : BindDGV(9,BindDataWithPage);   传递参数
/*
 private delegate void BindDGVDelegate(int n);
private void BindDGV(int n, BindDGVDelegate myDelegate)
{
    if (this.InvokeRequired)
    {
        this.Invoke(myDelegate, n);//同步
    }
    else
    {
        myDelegate(n);
    }
}
*/

/*  
    * Control的Invoke和BeginInvoke的委托方法是在主线程,即UI线程上执行的。
    * 也就是说如果你的委托方法用来取花费时间长的数据,然后更新界面什么的,
    * 千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,相对于invokeThread线程同步的,因为这些是依然阻塞UI线程的,造成界面的假死。
    * 用Thread来调用BeginInvoke和Invoke
    * 执行顺序:  A---  BC (B和C同时执行,B执行在线程UI上,C执行在线程beginInvokeThread上)  --DE
    
*/

private  Thread beginInvokeThread;
private   delegate   void  beginInvokeDelegate();
private   void  StartMethod()
{
    
// C代码段...... 耗费长时间的操作
    dataGridView1.BeginInvoke( new  beginInvokeDelegate(beginInvokeMethod));
    
// D代码段...... 删掉
}
private   void  beginInvokeMethod()
{
    
// E代码段  更新界面的方法。
    BindDataWithPage(pageindex);

}
private   void  BindDGV()
{
    
// A代码段.......
    beginInvokeThread  =   new  Thread( new  ThreadStart(StartMethod));
    beginInvokeThread.Start();
    
// B代码段......
}



///   <summary>
///  大于多少倍就报警
///   </summary>
///   <param name="dgv"></param>
///   <param name="n"></param>
public   bool  Alarm(DataGridView dgv,  int  n)
{
    
int  Space  =   0 int  Success  =   0 ;
    Dictionary
< string int >  dict  =  DictionaryColumns(dgv);
    
foreach  (KeyValuePair < string int >  kvp  in  dict)
    {
        
if  (kvp.Key  ==   " 2 " )
        {
            Space 
=  kvp.Value;
        }
        
if  (kvp.Key  ==   " 0 " )
        {
            Success 
=  kvp.Value;
        }
    }
    
if  (Space  >=  Success  *  n)
    {
        
// 报警
        
//  MessageBox.Show("报警!", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);                
        
return   true ;
    }
    
else
    {
        
// MessageBox.Show("bu报警!", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
         return   false ;
    }

}

        


public  Dictionary < string int >  DictionaryColumns(DataGridView dgv)
{
    Dictionary
< string int >  dct  =   new  Dictionary < string int > ();
    
string  str  =   ""
    
for  ( int  i  =   0 ; i  <  dgv.Rows.Count  -   1 ; i ++ )
    {               
            str 
=  Convert.ToString(dgv.Rows[i].Cells[ 4 ].Value);
                  
            
if  (dct.ContainsKey(str)) // 如果字典中已存在这个键,给这个键值加1
            {
                dct[str]
++ ;
            }
            
else
            {
                dct.Add(str, 
1 ); // 字典中不存在这个键,加入这个键
            }                  
    }
    
return  dct;
}


private  DateTime lastRefresh  =   new  DateTime( 0 );
private   int  refreshInterval  =   10 ;
private   string  lastTitle  =   string .Empty;
private   string  lastMessage  =   string .Empty;
     
   

///   <summary>
///  更新数据
///   </summary>
public   void  RefreshAllMessages()
{   
           
    BindDGV();
}

///   <summary>
///  更新待办事情
///   </summary>       
private   void  RefreshAsync()
{
    
// 更新最后执行时间
    UpdateLastRefreshTime();
    
// 建立查詢中状态
    BuildMessagesQuerying();
    
//  异步更新 为了不卡住
    RefreshAllMessagesDelegate refresher  =   new  RefreshAllMessagesDelegate( this .RefreshAllMessages);

    IAsyncResult result 
=  refresher.BeginInvoke( new  AsyncCallback(RefreshAllCallback), refresher);

    
// 等待更新完成
     while  ( ! result.IsCompleted)
    {
        Application.DoEvents(); 
// 在不加的时候,因为优先级的问题,程序会执行主进程的代码,再执行Tick的代码,而加了以后就可以同步执行。
    }
            
    
// 更新完成,警报并显示待办件数
    BuildMessagesResult();
}

///   <summary>
///  更新最后执行时间
///   </summary>
private   void  UpdateLastRefreshTime()
{
    
this .lastRefresh  =  DateTime.Now;
    
// 時間为n秒之間
    refreshInterval  =   int .Parse( this .txtRefreshInterval.Text);
    lblNextRefreshTime.Text 
=  String.Format( " {0:yyyy/MM/dd HH:mm:ss} " , lastRefresh.AddSeconds(refreshInterval)); ;
}

///   <summary>
///  建立查詢中状态
///   </summary>
private   void  BuildMessagesQuerying()
{
    lastMessage 
=   " 正在检查中..... " ;
    
//   linkTodo.Enabled = false;
    
//   linkTodo.Text = lastMessage;
    btnRefresh.Enabled  =   false ;
    mnuExit.Enabled 
=   false ;
    txtRefreshInterval.Enabled 
=   false ;
    
//  將icon改成更新中,改成Refresh.ico
    ChangeNotifyIcon(NotifyIconType.Actions);
}

///   <summary>
///  依最后结果设定页面
///   </summary>
private   void  BuildMessagesResult()
{
    
bool  IsShowNotify  =  Alarm(dataGridView1, multiples);
           
    
// 如果有待办件数的话,就改成报警,否則就使用原始
    ChangeNotifyIcon(IsShowNotify  ?  NotifyIconType.Phonographe : NotifyIconType.rabbit);
           
    notifyIcon1.Text 
=  lastMessage;
    mnuExit.Enabled 
=   true ;            
    txtRefreshInterval.Enabled 
=   true ;    
    
if  (IsShowNotify  &&   this .WindowState  ==  FormWindowState.Minimized  ||  IsShowNotify)
    {
        
// 要显示通知信息       
        PlaySound( " msg.wav " true true false ); // 报警
        lastMessage  =   " 报警…… " ;
        notifyIcon1.ShowBalloonTip(
3000 this .Text,lastMessage, ToolTipIcon.Info);
    }
}


       
// 回异步调
public   delegate   void  RefreshAllMessagesDelegate();
static   void  RefreshAllCallback(IAsyncResult result)
{
    
// 委托
    Form1.RefreshAllMessagesDelegate dlgt  =  (Form1.RefreshAllMessagesDelegate)result.AsyncState;       
    
//  调用 EndInvoke 返回结果
    dlgt.EndInvoke(result);
}


///   <summary>
///  实时更新
///   </summary>
///   <param name="sender"></param>
///   <param name="e"></param>
private   void  refreshTimer_Tick( object  sender, EventArgs e)
{
    TimeSpan diff 
=  DateTime.Now  -   this .lastRefresh;            
    
if  (diff  >   new  TimeSpan( 0 , 0 , refreshInterval))
    {
        
// 更新
        StopSound();
        RefreshAsync();
    }
}


///   <summary>
///  更换NotifyIcon
///   </summary>
private   void  ChangeNotifyIcon(NotifyIconType notiType)
{
    
const   string  imageFolderName  =   " Resources " ;
    
try
    {
        
// 內嵌资源名称 namespace.foldername.filename 而且大小写要相同哦  图片-右键属性-嵌入的资源
        System.Reflection.Assembly asm  =  System.Reflection.Assembly.GetExecutingAssembly();
        
string  fileName  =  asm.GetName().Name  +   " . "   +  imageFolderName  +   " . "   +  notiType.ToString()  +   " .ico " ;
        Stream iconStream 
=  asm.GetManifestResourceStream(fileName);
        Icon newIcon 
=   new  Icon(iconStream);
        
this .notifyIcon1.Icon  =  newIcon;
        iconStream.Close();
    }
    
catch  (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

public   enum  NotifyIconType
{
    rabbit,
    Actions,
    Phonographe
}





#region  报警声音
/*  当例如监测xx大于xx
* 通过PlaySound(”msg.wav”, true, true, false)方法实现连续报警
* 还可以同时弹出窗口提醒之类的信息.
* 关闭报警通过方法StopSound()实现就可以了.
*/

[DllImport(
" winmm.dll " , EntryPoint  =   " PlaySound " )]
private   static   extern   bool  Win32_PlaySound( string  pszSound, IntPtr hmod,  uint  fdwSound);

///   <summary>
///  播放一个wav音频文件
///   </summary>
///   <param name="path"></param>
///   <param name="asynchronous"></param>
///   <param name="loop"></param>
///   <param name="doNotStopPlay"></param>
public   static   void  PlaySound( string  path,  bool  asynchronous,  bool  loop,  bool  doNotStopPlay)
{
    Win32_PlaySound(path, IntPtr.Zero, (
uint )((asynchronous  ?
    PlaySoundMessage.SND_ASYNC : PlaySoundMessage.SND_SYNC) 
|  (loop  ?
    PlaySoundMessage.SND_LOOP : 
0 |  (doNotStopPlay  ?
    PlaySoundMessage.SND_NOSTOP : 
0 |  PlaySoundMessage.SND_FILENAME));
}

///   <summary>
///  停止播放
///   </summary>  
public   static   void  StopSound()
{
    Win32_PlaySound(
null , IntPtr.Zero,  0 );
}

[Flags()]
internal   enum  PlaySoundMessage
{
    SND_SYNC 
=   0x0000 ,
    SND_ASYNC 
=   0x0001 ,
    SND_LOOP 
=   0x0008 ,
    SND_NOSTOP 
=   0x0010 ,
    SND_FILENAME 
=   0x00020000
}
#endregion


#region  窗体事件
private   void  notifyIcon1_DoubleClick( object  sender, EventArgs e)
{
    ShowForm();
}

private   void  ShowForm()
{
    
if  ( this .WindowState  ==  FormWindowState.Minimized)
    {
        
this .Show();
        
this .WindowState  =  FormWindowState.Normal;
    }
    
this .Activate();
    
this .Focus();
}


private   void  mnuExit_Click( object  sender, EventArgs e)
{
    
this .WindowState  =  FormWindowState.Minimized;
    Close();
}

///   <summary>
///  視窗关闭,程序并不关闭,而是最小化
///   </summary>
///   <param name="sender"></param>
///   <param name="e"></param>
private   void  Form1_FormClosing( object  sender, FormClosingEventArgs e)
{
    
if  ( this .WindowState  !=  FormWindowState.Minimized)
    {
        e.Cancel 
=   true ;
        
this .WindowState  =  FormWindowState.Minimized;
        notifyIcon1.Tag 
=   string .Empty;
        notifyIcon1.ShowBalloonTip(
3000 this .Text,  " 程序未结束,要结束请在图示上按右键,选取结束功能! " , ToolTipIcon.Info);
    }
}

///   <summary>
///  在NotifyBallonTip上按下Click,就將Form开启出來
///   </summary>
///   <param name="sender"></param>
///   <param name="e"></param>
private   void  notifyIcon1_BalloonTipClicked( object  sender, EventArgs e)
{         
    ShowForm();   
}
#endregion

private   void  btnSetting_Click( object  sender, EventArgs e)
{
    Setting st 
=   new  Setting();
           
    st.Show();
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值