一個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, 00where);
    dataGridView1.DataSource 
= dt;
    winFormPager1.RecordCount 
= Convert.ToInt32(sa.ExecuteDataTable(table, field, orderby, 10, Index, 10where).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 = 0int Success = 0;
    Dictionary
<stringint> dict = DictionaryColumns(dgv);
    
foreach (KeyValuePair<stringint> 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<stringint> DictionaryColumns(DataGridView dgv)
{
    Dictionary
<stringint> dct = new Dictionary<stringint>();
    
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"truetruefalse);//報警
        lastMessage = "報警……";
        notifyIcon1.ShowBalloonTip(
3000this.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(
3000this.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();
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章