2015-01-20 2 views
0

그래서 나는 클라이언트가 청취자 역할을하는 while 루프에서 아래 작업을 수행하는 서버를 가지고 있습니다. 문제는 클라이언트를 통해 최대한 빨리 루프를 돌리는 것처럼 보입니다. 그러나 이전 작업이 완료되기 전에 너무 빨리 작업을 시작합니다 (같은 클라이언트의 경우).작업 관리 및 사용?

작업이 완료 될 때까지 기다리지 않으려 고합니다. 더 많은 작업을 수행하고 싶지만 이미 기존 작업이있는 특정 클라이언트에 대해서는 더 이상 작업을 만들지 말아야합니다.

이 작업을 수행하는 가장 좋은 방법은 무엇입니까 ... 많은 사람들이 WhenAll 또는 무엇인가 사용하고 있지만 모든 작업에 신경 쓰지는 않습니다. 당신이 이전이 완료 될 때까지 해당 클라이언트에 대한 새로운 작업을 시작하지 않으려면

//the below is in a while loop which goes through the clients that are connected. 
    if (stream.DataAvailable) 
        { 
// the below task is the one that is firing before the pervious fired one completes. 
         Task DataInterpetTask = Task.Factory.StartNew(() => 
         { 
          int totalBuffer, totalRecieved = 0; 
          byte[] totalBufferByte = new byte[4]; 
          byte[] buffer = new byte[0]; 
          byte[] tbuffer; 
          int rLength, prevLength; 
          stream.Read(totalBufferByte, 0, 4); 
          totalBuffer = BitConverter.ToInt32(totalBufferByte, 0); 
          Console.WriteLine("got stuff: " + totalBuffer); 
          byte[] buf = new byte[c.getClientSocket().ReceiveBufferSize]; 
          while (totalBuffer > totalRecieved) 
          { 

           rLength = stream.Read(buf, 0, buf.Length); 
           totalRecieved = rLength + totalRecieved; 
           if (rLength < buf.Length) 
           { 
            byte[] temp = new byte[rLength]; 
            Array.Copy(buf, temp, rLength); 
            buf = temp; 
           } 
           prevLength = buffer.Length; 
           tbuffer = buffer; 
           buffer = new byte[buffer.Length + rLength]; 
           Array.Copy(tbuffer, buffer, tbuffer.Length); 
           buf.CopyTo(buffer, prevLength); 
          } 

          String msg = Encoding.ASCII.GetString(buffer); 
          if (msg.Contains("PNG") || msg.Contains("RBG") || msg.Contains("HDR")) 
          { 
           Console.WriteLine("Receiving Picture"); 
           RowContainer tempContainer; 
           if ((tempContainer = MainWindow.mainWindow.RowExists(c)) != null) 
           { 
            tempContainer.Image = buffer; 
            Console.WriteLine("Updating row: " + tempContainer.rowNumber); 
            MainWindow.mainWindowDispacter.BeginInvoke(new Action(() => 
             MainWindow.mainWindow.UpdateRowContainer(tempContainer, 0))); 
           } 
           else 
           { 
            Console.WriteLine("Adding row for Picture"); 
            MainWindow.mainWindowDispacter.BeginInvoke(new Action(() => 
             MainWindow.mainWindow.CreateClientRowContainer(c, buffer))); 
           } 
           return; 
          } 


          String switchString = msg.Substring(0, 4); 
          if (msg.Length > 4) 
           msg = msg.Substring(4); 
          MainWindow.mainWindowDispacter.BeginInvoke(new Action(() => 
          { 
           if (MainWindow.debugWindow != null) 
            MainWindow.debugWindow.LogTextBox.AppendText("Received message " + msg + " from client: " + c.getClientIp() + " as a " + switchString + " type" + Environment.NewLine); 

          })); 
          RowContainer tContain = MainWindow.mainWindow.RowExists(c); 
          if(tContain == null) 
           return; 
          switch (switchString) 
          { 
           case "pong": 
            c.RespondedPong(); 
            break; 
           case "stat": 
            tContain.SetState(msg); 
            MainWindow.mainWindow.UpdateRowContainer(tContain, 1); 
            break; 
           case "osif": 
            tContain.Os = msg; 
            MainWindow.mainWindowDispacter.BeginInvoke(new Action(() => 
             MainWindow.mainWindow.UpdateRowContainer(tContain, 2))); 
            break; 
           case "idle": 
            tContain.idle = msg; 
            MainWindow.mainWindowDispacter.BeginInvoke(new Action(() => 
             MainWindow.mainWindow.UpdateRowContainer(tContain, 3))); 
            break; 
          } 
         }); 
        } 

답변

0

, 다음 그냥 추적합니다. 루프에서 처리중인 클라이언트 목록에도 없도록 클라이언트 오브젝트를 "진행 중"목록으로 이동하거나 조작이 "진행 중"임을 나타내는 플래그를 클라이언트 오브젝트 클래스에 추가하십시오 따라서 루프는 현재 작업이 완료 될 때까지 클라이언트를 무시할 수 있습니다 (예 : if (c.OperationInProgress) continue;).

즉, I/O 관리를 위해 폴링 (예 : DataAvailable 확인)을 사용하고있는 것으로 보입니다. 이는 실제로 비효율적 인 접근 방법이며, 그 중 가장 중요한 것은 현재 문제의 근본 원인입니다. 훨씬 더 비동기식 모델을 사용한다면 코드가 더 효율적일 것입니다. 비동기식 API는 주어진 상태에서 오버랩 된 연산을 피하기 위해 필요한 모든 상태 관리를 제공하기 때문에이 문제조차 없습니다. 고객.

불행히도 코드 예제가 매우 희박하여 특정 비동기 모델을 사용하도록 구현을 변경하는 방법에 대한 조언 (많은 작은 코드가 있음)을 제공해야합니다. a good code example에는없는 추가 코드가 있음). 위의 내용을 따르면 적절한 솔루션을 제공 할 수 있습니다.