2011-05-23 228 views
0

我遇到了一個問題,管理.NET 4.0 C#上的線程,而且我的線程知識還不足以解決它,所以我在這裏發佈它期望有人可以給我一些建議請。處理多線程的線程

的情況如下:

我們有C#4.0框架Windows服務:(1)通過插座連接到服務器以獲得.PCM文件,(2),然後將其轉換爲一個.WAV文件,(3)通過電子郵件發送 - SMTP,最後(4)通知初始服務器它已成功發送。

已安裝服務的服務器有8個處理器和8 GB或RAM。

爲了允許多處理我已經用4個線程構建了服務,它們中的每一個都執行前面提到的每個任務。

在代碼中,我對每個任務的類和方法,所以我創建線程和調用方法如下:

Thread eachThread = new Thread(object.PerformTask); 

裏面每一個方法我有一個檢查一個而如果的連接套接字處於活動狀態,並根據其porpuse繼續獲取數據或處理數據。

while (_socket.Connected){ 
//perform task 
} 

的問題是,由於正在安裝更多的服務(相同的Windows服務被複制和兩個端點之間所指向的服務器通過插座來獲取文件上)的CPU消耗急劇增加,每個服務繼續運行,處理文件,但有一段時間CPU消耗太高,服務器崩潰。

問題是:你會建議我如何處理這種情況,我的意思是一般而言,處理這種高度要求的處理任務以避免服務器在CPU消耗中崩潰的好方法是什麼?

謝謝。

PS .:如果有人需要關於該場景的更多細節,請告訴我。

編輯1

隨着CPU崩潰我的意思是服務器過於緩慢,我們不得不重新啓動它。

編輯2

我在這裏張貼代碼的某些部分,所以你可以得到它是如何編程的想法:

while(true){ 
      //starting the service  
      try 
      { 
       IPEndPoint endPoint = conn.SettingConnection(); 
       string id = _objProp.Parametros.IdApp; 

       using (socket = conn.Connect(endPoint)) 
       { 
        while (!socket.Connected) 
        { 
         _log.SetLog("INFO", "Conectando socket..."); 
         socket = conn.Connect(endPoint); 

         //if the connection failed, wait 5 seconds for a new try. 
         if (!socket.Connected) 
         { 
          Thread.Sleep(5000); 
         } 
        } 

        proInThread = new Thread(proIn.ThreadRun); 
        conInThread = new Thread(conIn.ThreadRun); 
        conOutThread = new Thread(conOut.ThreadRun); 

        proInThread.Start(); 
        conInThread.Start(); 
        conOutThread.Start(); 

        proInThread.Join(); 
        conInThread.Join(); 
        conOutThread.Join(); 
       } 
      } 
    } 

編輯3

  • 主題1

    while(_socket。連接) { 嘗試 { } var conn = new AppConection(ref _objPropiedades);

       try 
           { 
            string message = conn.ReceiveMessage(_socket); 
            lock (((ICollection)_queue).SyncRoot) 
            { 
             _queue.Enqueue(message); 
             _syncEvents.NewItemEvent.Set(); 
             _syncEvents.NewResetEvent.Set(); 
            } 
            lock (((ICollection)_total_rec).SyncRoot) 
            { 
    
             _total_rec.Add("1"); 
            } 
           } 
           catch (SocketException ex) 
           { 
            //log exception 
    
           } 
           catch (IndexOutOfRangeException ex) 
           { 
            //log exception 
           } 
           catch (Exception ex) 
           { 
            //log exception 
    
           } 
           //message received 
    
          } 
          catch (Exception ex) 
          { 
           //logging error 
          } 
         } 
    
         //release ANY instance that could be using memory 
         _socket.Dispose(); 
         log = null; 
    
  • 線程2

    而(_socket.Connected) { 嘗試{ _syncEvents.NewItemEventOut.WaitOne();

        if (_socket.Connected) 
            { 
             lock (((ICollection)_queue).SyncRoot) 
             { 
    
              total_queue = _queue.Count(); 
    
             } 
    
             int i = 0; 
             while (i < total_queue) 
             { 
              //EMail Emails; 
              string mail = ""; 
              lock (((ICollection)_queue).SyncRoot) 
              { 
    
               mail = _queue.Dequeue(); 
    
               i = i + 1; 
              } 
              try 
              { 
               conn.SendMessage(_socket, mail); 
               _syncEvents.NewResetEvent.Set(); 
              } 
              catch (SocketException ex) 
              { 
               //log exception 
              } 
             } 
            } 
            else 
            { 
             //log exception 
    
             _syncEvents.NewAbortEvent.Set(); 
             Thread.CurrentThread.Abort(); 
            } 
           } 
           catch (InvalidOperationException e) 
           { 
            //log exception 
           } 
           catch (Exception e) 
           { 
            //log exception 
           } 
         } 
    
         //release ANY instance that could be using memory 
         _socket.Dispose(); 
         conn = null; 
         log = null; 
    
  • 線程3

    而(_socket.Connected) {

       int total_queue = 0; 
           try 
          { 
           _syncEvents.NewItemEvent.WaitOne(); 
           lock (((ICollection) _queue).SyncRoot) 
           { 
            total_queue = _queue.Count(); 
           } 
           int i = 0; 
           while (i < total_queue) 
           { 
            if (mgthreads.GetThreatdAct() < 
    

    mgthreads.GetMaxThread()){ 字符串消息= 「」; 鎖(((ICollection的)_queue).SyncRoot) {

          message = _queue.Dequeue(); 
              i = i + 1; 
    
             } 
             count++; 
             lock (((ICollection) _queueO).SyncRoot) 
             { 
              app.SetParameters(_socket, _id, 
    

    消息,_queueO,_syncEvents, _total_Env,_total_err); }

         Thread producerThread = new 
    

    螺紋(app.ThreadJob){名稱= 「ProducerThread_」 + DateTime.Now.ToString( 「ddMMyyyyhhmmss」), 優先級= ThreadPriority.AboveNormal }; producerThread.Start();

         producerThread.Join(); 
    
             mgthreads.IncThreatdAct(producerThread); 
            } 
            mgthreads.DecThreatdAct(); 
           } 
           mgthreads.DecThreatdAct(); 
          } 
          catch (InvalidOperationException e) 
          { 
    
          } 
          catch (Exception e) 
          { 
    
          } 
          Thread.Sleep(500); 
         } 
    
         //release ANY instance that could be using memory 
         _socket.Dispose(); 
         app = null; 
         log = null; 
         mgthreads = null; 
    
  • 螺紋4

    MessageVO mesVo = fac.ParseMessageXml(_message);

+0

你能定義「服務器CPU消耗崩潰」嗎? – Olaf 2011-05-23 17:24:39

+0

你能定義你的意思嗎?「問題在於隨着更多服務的安裝」。這是否意味着更多的線程正在運行或更多的進程?線程如何確定要執行的任務? – usr 2011-05-23 17:32:08

+0

你可以定義多少「更多」。你的大部分線程聽起來像是對我的串行操作,還是你在一個服務中處理了很多? – sra 2011-05-23 17:41:39

回答

0

我會降低線程的優先級,並有所有線程通過一個信號量限制併發到Environment.ProcessorCount。這不是一個完美的解決方案,但它聽起來像是在這種情況下是足夠的,而且很容易修復。

編輯:想想看,您必須將10個服務合併到一個進程中,否則您將無法集中控制正在運行的線程。如果你有10個獨立的進程,他們不能協調。

+0

這是非常有用的,如果你的任務實際上需要長時間的純cpu計算。 – Alireza 2011-05-23 17:28:55

+0

您發佈的代碼看起來不會不必要地旋轉。我找不到它的問題。做到這一點:運行服務直到它變熱,然後停止調試器,查看所有正在運行的腳本及其調用堆棧。你可能會發現一些有趣的東西。至少你會發現熱點。 – usr 2011-05-23 17:53:25

+0

做了一個編輯... – usr 2011-05-23 18:04:17

0

由於CPU使用率高,通常應該不會崩潰。當任何線程正在等待遠程發生的事件(例如遠程服務器響應請求)時,該線程不使用cpu資源。但是實際上它正在做某些事情,因此它會相應地使用cpu。在你提到的任務中,沒有固有的高CPU使用率(因爲WAV文件的保存不需要複雜的算法),所以CPU的高使用率似乎是編程錯誤的標誌。

+0

謝謝,我不知道。 – lidermin 2011-05-23 19:41:19