2016-09-16 4 views
4

이더넷에서 원시 데이터를 가져올 간단한 UDP-to-Chart 응용 프로그램 (예 : Windows 용)을 작성하고 특정 방식으로 작성하려고합니다. 차트에. 여기에 지금까지이 작업은 다음과 같습니다C# : 차트 :받은 UDP 패킷에서 데이터를 넣는 가장 빠른 방법

if (graphicOn) 
{ 
    for (i = 0; i < 32; i++) 
    { 
     graphicData[i + (graphicStep * 32)] = bigDataIn[i * 32 + graphicChan]; 
    } 
    graphicStep++; 
    if (graphicStep == 32) graphicStep = 0; 
    try 
    { 
     Invoke(new Action(() => { chartGraphic.Series["DataGraphic"].Points.DataBindXY(graphicEnum, graphicData); 
     })); 
    } 
    catch 
    { 
    } 
} 

과 : (즉, 특정 방법으로 모든 패킷의 내용을 보여줍니다)

public void serverThread() 
    { 
     UdpClient udpClient = new UdpClient(Convert.ToInt16(tbEthPort.Text)); 
     while (_serverWork) 
     { 
      try 
      { 
       IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, Convert.ToInt16(tbEthPort.Text)); 
       Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint); 
       if (receiveBytes.Length > 0) 
        for (i = 0; i < receiveBytes.Length; i++) 
        { 
         bigDataIn[i] = receiveBytes[i]; 
        } 

을하고 두 번째 차트를 그릴 : 두 개의 차트 양식, 스레드는 UDP 패킷을받을 수 첫 번째 차트를 그리는 타이머가있는 메인 스레드.

private void tmrHisto_Tick(object sender, EventArgs e) 
    { 
     int[] slice = new int[32]; 
     for (int i = 0; i < 32; i++) 
      slice[i] = bigDataIn[i + 32 * histogramArrayStep]; 

     histogramArrayStep++; 
     if (histogramArrayStep == 32) histogramArrayStep = 0; 

     chartHistogram.Series["DataHistogram"].Points.Clear(); 
     for (int i = 0; i < HISTO_XMAX; i++) 
     { 
      chartHistogram.Series["DataHistogram"].Points.AddXY(i, slice[i]); 
     } 
    } 

모든 것이 내 PC에 잘 작동, 그리고 몇몇 다른 사람,하지만 난 오래된 PC의 내 응용 프로그램을 시작할 때, 내 응용 프로그램은 느슨한 패킷에 시작합니다. InvokechartGraphic으로 시작하면 패킷 손실이 시작됩니다. WireShark에서 손실없이 모든 패킷 (약 20 초)을 볼 수 있습니다. 타이머 간격이 150ms 대신 50ms로 설정되었을 때 같은 문제가 발생했지만 더 이상 간격을 늘릴 수 없습니다.

그래서 제 질문입니다. 그래픽 드로잉의 속도를 높이고 저사양 PC의 패킷 손실을 막을 수 있습니까? 아니면 디버깅 중에 로우 엔드 PC를 에뮬레이트 할 수 있습니까?

답변

2

Invoke은 블로킹이므로 도면 (DataBindXY)이 완료 될 때까지 입금액이 대기합니다. 수신 스레드 외부로 이동하십시오.

순환 버퍼는 빠르게 보이지만 참조 만 보유하고있는 것으로 보입니다. 이것은 많이 향상되지 않습니다. 게다가 udpClient에서 새 버퍼를 얻는 중입니다. Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint); 순환 버퍼는 '오래된'메모리가 재사용 될 때만 유용합니다.

수신 대기열에서 대기열/타이머로 데이터를 전달하는 동시 대기열을 시도하십시오. 리 바인드/드로잉이 동시 대기열의 잠금 외부에 있는지 확인하십시오. 이제 성능이 데이터 그램을 수신하게됩니다.


UPDATE :

일부 의사 코드 :

돌아 가기 :

private List<byte[]> datagrams = new List<byte[]>(); 

public void serverThread() 
{ 
    UdpClient udpClient = new UdpClient(Convert.ToInt16(tbEthPort.Text)); 
    while (_serverWork) 
    { 
     try 
     { 
      IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, Convert.ToInt16(tbEthPort.Text)); 
      Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint); 

      // add to the queue 
      lock (datagrams) 
       datagrams.Add(receiveBytes); 
     } 
    } 
} 

GUI :

private Timer timer = new Timer(); 

public void timer_Tick(object sender, EventArgs e) 
{ 
    byte[][] data; 

    // lock the queue as short as possible. (create a copy with ToArray()) 
    // this way the receive thread can run again.. 
    // this is also know as bulk processing.. 
    lock (datagrams) 
    { 
     data = datagrams.ToArray(); 
     datagrams.Clear(); 
    } 

    // if no packets received, don't update anything 
    if(data.Length == 0) 
     return; 

    // process the received data (multiple datagrams) 
    for(byte[] item in data) 
    { 
     ... 
    } 
    // Update chart 
} 

대기열이 너무 커지지 않는지 확인할 수 있습니다. 이 경우 대기열 처리 속도가 너무 느립니다. itemcount를 제한 할 수 있습니다.

+0

UDP 수신기는 MSDN에서 가져옵니다. 나는 드로잉을 다른 스레드로 옮기려고 시도했으나 실패했습니다. C#의 경험이 부족합니다. 아마도 거기에'Invoke'를 사용했기 때문에 ... 호출을 피하려고합니다. – Vanechka

+0

예제를 추가했습니다. –

+0

답을 고맙지 만, 저에게 잘 작동하지 않습니다. 왜냐하면 데이터를받을 때마다 내 'chartGraphic'을 업데이트해야하고 타이머 틱으로 chartHistogram을 업데이트해야하기 때문입니다 ... – Vanechka

관련 문제