C#關於軟件界面無響應、BUG報警、程序異常退出等情況的監控和報警


對程序的監控,一般采用另外一個進程進行監控(即主進程和監控進程),主進程運行后,先查找下看有沒有還在殘留運行的監控進程,如果有先結束監控進程,然后重新啟動。

如何監控主程序的思路是:主程序中開辟一個共享內存映射文件,通過定時器向文件寫入變化的信號數據(自定義)。監控程序定時從共享內存文件中讀取信號數據,並和上次讀取的信號數據進行對比,如果不一致表示主程序運行正常,如果不一致,表示運行異常或者程序異常退出。

內存映射文件

內存映射文件是由一個文件到進程地址空間的映射。

        C#提供了允許應用程序把文件映射到一個進程的函(MemoryMappedFile.CreateOrOpen)。內存映射文件與虛擬內存有些類似,通過內存映射文件可以保留一個地址空間的區域,同時將物理存儲器提交給此區域,只是內存文件映射的物理存儲器來自一個已經存在於磁盤上的文件,而非系統的頁文件,而且在對該文件進行操作之前必須首先對文件進行映射,就如同將整個文件從磁盤加載到內存。由此可以看出,使用內存映射文件處理存儲於磁盤上的文件時,將不必再對文件執行I/O操作,這意味着在對文件進行處理時將不必再為文件申請並分配緩存,所有的文件緩存操作均由系統直接管理,由於取消了將文件數據加載到內存、數據從內存到文件的回寫以及釋放內存塊等步驟,使得內存映射文件在處理大數據量的文件時能起到相當重要的作用。另外,實際工程中的系統往往需要在多個進程之間共享數據,如果數據量小,處理方法是靈活多變的,如果共享數據容量巨大,那么就需要借助於內存映射文件來進行。實際上,內存映射文件正是解決本地多個進程間數據共享的最有效方法。

        共享內存是內存映射文件的一種特殊情況,內存映射的是一塊內存,而非磁盤上的文件。共享內存的主語是進程(Process),操作系統默認會給每一個進程分配一個內存空間,每一個進程只允許訪問操作系統分配給它的哪一段內存,而不能訪問其他進程的。而有時候需要在不同進程之間訪問同一段內存,怎么辦呢?操作系統給出了創建訪問共享內存的API,需要共享內存的進程可以通過這一組定義好的API來訪問多個進程之間共有的內存,各個進程訪問這一段內存就像訪問一個硬盤上的文件一樣。而.Net 4.0中引入了System.IO.MemoryMappedFiles命名空間,這個命名空間的類對windows 共享內存相關API做了封裝,使.Net程序員可以更方便的使用內存映射文件。

內存映射文件實現進程間通訊

        內存映射文件是實現進程通訊的又一種方法,我們可以通過共享剪貼板、共享物理文件來實現進程間的數據共享,這里我們還可以通過內存映射文件來實現共享,這樣,文件內的數據就可以用內存讀/寫指令來訪問,而不是用ReadFile和WriteFile這樣的I/O系統函數,從而提高了文件存取速度。這種方式更加快捷高效,最適用於需要讀取文件並且對文件內包含的信息做語法分析的應用程序,如:對輸入文件進行語法分析的彩色語法編輯器,編譯器等。這種數據共享是讓兩個或多個進程映射同一文件映射對象的視圖,即它們在共享同一物理存儲頁。這樣,當一個進程向內存映射文件的一個視圖寫入數據時,其他的進程立即在自己的視圖中看到變化。

注意:

        對文件映射對象要使用同一名字。

        是讓兩個或多個進程映射同一文件映射對象的視圖,即它們在共享同一物理存儲頁。這樣,當一個進程向內存映射文件的一個視圖寫入數據時,其他的進程立即在自己的視圖中看到變化。但要注意,對文件映射對象要使用同一名字。

公用類:

 1 /// <summary>
 2     /// 進程間通訊,共享映射文件
 3     /// </summary>
 4     public class MappingHelper
 5     {
 6         long capacity = 1024 * 1024;
 7         public MemoryMappedFile file;
 8 
 9         public MappingHelper()
10         {
11         }
12 
13         public MappingHelper(string fileName,string mapName)
14         {
15             file = MemoryMappedFile.CreateFromFile(fileName,FileMode.OpenOrCreate,mapName,capacity);
16         }
17         
18         /// <summary>
19         /// 將消息寫入共享映射文件
20         /// </summary>
21         /// <param name="msg">消息內容</param>
22         public void WriteString(string msg)
23         {
24             using (var stream = file.CreateViewStream())
25             {
26                 using (var writer = new BinaryWriter(stream))
27                 {
28                     writer.Write(msg);
29                 }
30             }
31         }
32         /// <summary>
33         /// 從共享映射文件中讀取消息
34         /// </summary>
35         /// <returns></returns>
36         public string ReadString()
37         {
38             using (var stream = file.CreateViewStream())
39             {
40                 using (var reader = new BinaryReader(stream))
41                 {
42                     List<byte> bytes = new List<byte>();
43                     byte[] temp = new byte[1024];
44                     while (true)
45                     {
46                         int readCount = reader.Read(temp, 0, temp.Length);
47                         if (readCount == 0)
48                         {
49                             break;
50                         }
51                         for (int i = 0; i < readCount; i++)
52                         {
53                             bytes.Add(temp[i]);
54                         }
55                     }
56                     if (bytes.Count > 0)
57                     {
58                         return Encoding.Default.GetString(bytes.ToArray()).Replace("\0", "");
59                     }
60                     else
61                     {
62                         return null;
63                     }
64                 }
65             }
66         }
67     }
View Code

主程序:

 //將指定文件映射到內存中,監控進程讀取時,要用一樣的內存映射名
_MappingHelper=new MappingHelper("path","內存中的映射名");
//通過定時器定時寫入變化的數據信號
private void _Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _MappingHelper.WriteString(DateTime.Now.ToString("yyyyMMddHHmmss"));
        }
View Code

監控程序:

 1 public static void Main(string[] args)
 2         {
 3             try
 4             {
 5                 mhHelper.file = MemoryMappedFile.OpenExisting("主程序創建的內存映射文件名");
 6                 string laststr = "";
 7                 do
 8                 {                    
 9                      //讀取被監控進程定時發送的數據
10                     string tempstr = mhHelper.ReadString();
11                     if (tempstr == laststr)//表示程序死機或異常退出
12                     {
13                         //此處進行異常處理..................
14                         DisposeMemoryMapFile();
15                         Process.GetCurrentProcess().Kill();
16                     }
17                     else
18                     {
19                         laststr = tempstr;
20                     }
21 
22                     Thread.Sleep(2000);
23                 }
24                 while (true);
25             }
26             catch (Exception e)
27             {
28                 
29             }
30         }                        
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM