C # - События и делегаты при получении данных - PullRequest
0 голосов
/ 10 мая 2018

Я хочу отображать строку при получении данных с сервера. Для этого я думал об использовании делегатов и событий. Я новичок в этой теме (делегаты и события), поэтому мне не удалось это настроить. Вот что я сделал:

public delegate void ClientHandleData(byte[] data, int bytesRead);
public event ClientHandleData OnDataReceived;

public void ConnectToServer(string ipAddress, int port)
{
    this.port = port;
    tcpClient = new TcpClient(ipAddress, port);
    clientStream = tcpClient.GetStream();

    Thread t = new Thread(new ThreadStart(ListenForData));
    started = true;
    t.Start();
}
private void ListenForData()
{
   int bytesRead;

   while (started)
   {
      bytesRead = 0;

      try
      {
          bytesRead = clientStream.Read(buffer.ReadBuffer, 0, readBufferSize);      
      }
      catch
      {
        //A socket error has occurred
        MessageBox.Show("A socket error has occurred);
        break;
      }

      if (OnDataReceived != null)
      {

                // display string to a textbox on the UI
      }

    Thread.Sleep(15);
   }

   started = false;

   Disconnect();
}

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Давайте посмотрим на ваш код прослушивания TcpClient. Когда вы звоните stream.Read(), вы не можете быть уверены, сколько данных будет прочитано из вашего сокета, поэтому вы должны читать до конца потока, или вы должны знать, какую дату вы должны прочитать из сокета. Допустим, вы знаете, сколько данных вы должны прочитать

var readSofar = 0;
var iNeedToRead = 500;//500Bytes
try{
    while(readSoFar<iNeedToRead){
       var readFromSocket = clientStream.Read(buffer.ReadBuffer, readSofar, readBufferSize-readSofar);
       if(readFromSocket==0){
         //Remote server ended your connection or timed out etc
         //Do your error handling may be stop reading
       } 
       readSofar += readFromSocket;
    }

    }
     catch {
       //A socket error has occurred
       MessageBox.Show("A socket error has occurred);
       break;
     }
 if (OnDataReceived != null){
    // display string to a textbox on the UI
 }

Вы можете использовать нулевой оператор распространения, как этот.

OnDataReceived?.Invoke(buffer.ReadBuffer, bytesRead);

Если вы используете WindowsForm, каждый контроллер должен обновляться из потока пользовательского интерфейса, поэтому вы должны вызывать метод подписчика

private void IReceivedData(byte[] data, int count){
    this.Invoke(()=>{...Your code});
}
0 голосов
/ 10 мая 2018

Вы можете просто написать

OnDataReceived?.Invoke(buffer.ReadBuffer, bytesRead);

Если вы хотите быть уверены, что ваше событие не будет установлено на null после оператора if, вы можете сделать это:

var handler = OnDataReceived;
handler?.Invoke(buffer.ReadBuffer, bytesRead);

Будьте осторожны при обновлении пользовательского интерфейса, потому что вы можете обновлять пользовательский интерфейс только из потока пользовательского интерфейса.Если вы используете WPF, вы можете сделать это:

Dispatcher.Invoke(() => {
   // Update your UI.
});

А также убедиться, что кто-то действительно подписался на событие:

public void Foo()
{
    objectWithTheEvent.OnDataReceived += OnOnDataReceived;
}

private void OnOnDataReceived(byte[] data, int count)
{

}
...