套接字:接收和发送之间的延迟(WriteStream.WriteAsync() 和 ReadStream.ReadAsync())

Sockets: delay between receive and send (WriteStream.WriteAsync() and ReadStream.ReadAsync())

如何在使用 WriteStream.WriteAsync() 发送字符串和使用 ReadStream.ReadAsync 等待响应之间正确实现延迟()?

我正在使用 rda.SocketsForPCL 插件创建 TCP 客户端套接字,然后创建相应的读写流。

当我使用 TimeSpan.FromMilliseconds(200)) 实现延迟时,我得到一个 System.NullReferenceException: Object reference not set to an instance of an object in VS 2017。我是 C# 的新手并且Xamarin 和我不确定如何实现除上述方法之外的不会导致抛出异常的延迟。

是否有 "Global" 异常处理程序可以以某种方式实现以处理诸如此类的异常,因为 VS 2017 不会破坏代码并向您准确显示异常实际发生的位置?

我在 Xamarin.Forms 中实现了下面的 activity 页面,但它不允许我使用 TimeSpan.FromMilliseconds(200)); 在下面的 UpdateUserDataAsync() 函数中注释:

 public InputPage ()
{
    try
    {
        InitializeComponent();
    }
    catch (Exception ex)
    {
        string err = ex.Message;
        throw;
    }

    client = SharedSocket.Instance().getSocket();                   // Get persistent Socket ===> client connection
    UpdateUserDataAsync();                                          // Used to update the contents of the Listview
    loadSampleData();                                               // Load the Items in the ListView   

    BindingContext = this;

    this.BindingContext = new Relays();                             // Binding the Listview items
    var neg = lstView.BindingContext as Relays;
    InputID = neg.ID;
}

private async void UpdateUserDataAsync()                        // Request and Receive Controller Name
{
    byte[] rv = new byte[] { 0x01, 0x01, 0x01 0x01, 0x01, 0x01, 0x01 };    // Request
    Send_CntrP(rv);                                             // Send request
   //await Task.Delay(TimeSpan.FromMilliseconds(200));
rec2 = await ReceiveByte();
}// UpdateUserDataAsync

private void loadSampleData()
{
    ObservableCollection<Relays> lisInputs = new ObservableCollection<Relays>();

    if (rec2.Length >= 4)
    {
        byte[] states = Encoding.ASCII.GetBytes(rec2);      // Create byte array of received string

        for (int j=6; j<22; j++)
        {
            switch (states[j])
            {
                case 0x00:                                         
                  lisInputs.Add(new Relays { ID = j - 5, Name = "ERROR" + (j - 5), State = "ERROR" });
                    break;

                case 0x01:                                         
                  lisInputs.Add(new Relays { ID = j - 5, Name = "IOK" + (j - 5), ImageUrl = "round_on.png", State= "Toggle"});
                     break;

                case 0x02:                                          
                  lisInputs.Add(new Relays { ID = j - 5, Name = "IOK" + (j - 5), ImageUrl = "round_on.png", State = "ON"});
                    break;

                case 0x03:                                          
                  lisInputs.Add(new Relays { ID = j - 5, Name = "IOK" + (j - 5), ImageUrl = "round_on.png", State = "OFF"});
                    break;

                case 0x04:                                          
                  lisInputs.Add(new Relays { ID = j - 5, Name = "IOK" + (j - 5), ImageUrl = "round_on.png", State = "NO"});
                    break;

                case 0x05:                                         
                  lisInputs.Add(new Relays { ID = j - 5, Name = "IOK" + (j - 5), ImageUrl = "round_on.png", State = "NC"});
                    break;

                case 0x10:                                          
                  lisInputs.Add(new Relays { ID = j - 5, Name = "IOK" + (j - 5), ImageUrl = "round_on.png", State = "SC"});
                    break;

                case 0x11:                                         
                  lisInputs.Add(new Relays { ID = j - 5, Name = "IOK" + (j - 5), ImageUrl = "round_on.png", State = "OC"});
                    break;
            }
        }
    }
    else
    {
        for (int i = 0; i < num; i++)
        {
            Images[i] = "round_off.png";
            InputName[i] = "ERROR";
            InputOn[i] = false;
            InputState[i] = "ERROR";

            lisInputs.Add(new Relays { Name = InputName[i] + i, ImageUrl = Images[i], ID = i, State = InputState[i] });
        }
    }

    lstView.ItemsSource = lisInputs;
}

public class MyListItemEventArgs : EventArgs
{
    public Relays MyItem { get; set; }

    public MyListItemEventArgs(Relays item)
    {
        this.MyItem = item;
    }
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// +++++++++++++++++++++++ Sending Messages+++++++++ +++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public async void Send_CntrP(byte[] Comms)
{
    var Len = Comms.Length;                                        // Read the byte array Length

    if (client.Socket.Connected && Len <= 23)                       // No longer than 22 bytes of data to be sent                        
    {
        try
        {
            await client.WriteStream.WriteAsync(Comms, 0, Len);    // Send data of specified Length
            await client.WriteStream.FlushAsync();                           // Make sure all the buffer output data is sent   
            await Task.Delay(TimeSpan.FromMilliseconds(200));      // Delay before next TX to ensure buffer is emptied correctly
        }
        catch (Exception ex)                                       // Exception Handler
        {
            return;
            throw ex;
        }
    }// Client Connected

    else
    {
        XFToast.ShortMessage("Error updating name.\n\rPlease check the connection or length of the entry");   //Android Native Toast Message
    }
}// Send_CntrP 
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++ Receiving Messages +++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public async Task<string> ReceiveByte()           // Receive messages Asynchronously
{
    int bytesRec = 0;
    var buffer = new byte[28];

    if (client.Socket.Connected)                  // Check Socket connection
    {      
        while (bytesRec != -1)                    // Read received data ---> byte-by-byte
        {
            try
            {
                bytesRec = await client.ReadStream.ReadAsync(buffer, 0, 28);
            }

            catch (Exception ex)                  // Exception Handler (to prevent App crash)
            {
                XFToast.ShortMessage("Error receiving message.\n\rPlease check the WIFI connection.");
                return "ERROR";                   // Return an "ERROR" message if failed
                throw ex;
            }

            var meh = buffer.ToArray();                              
            rec2 = System.Text.Encoding.UTF8.GetString(meh);         

            if (rec2.Length >= 1 && rec2.Length < 30)                
            {
                return await Task.FromResult(rec2);                  // Return a string 
            }
            else
            {
                //await DisplayAlert("Error", "Error receiving message.", "OK");
                XFToast.ShortMessage("Error receiving message.\n\rPlease verify the connection.");   //Android Native Toast Message
                return "ERROR";         // Return an "ERROR" message
            }
        }// Reading response 
    }// Client
    else
    {
        return err;     // Return a "Connection Error" string when no connection is available
    }

    return rec2;         // Return the received bytes in a string 
}// ReceiveByte
// 
  ++++++++++++++++++++++++++++++++++++++++++++++++
 }

很抱歉拖了这么久 post 但我已经为这个问题苦苦挣扎了一段时间,我没有足够的经验来处理所有的异步方法和异常 "finding" 然后使用 VS 2017 和 Xamarin 对其进行处理,因为我仍在学习基础知识:(

提前感谢您的任何 help/suggestions。

这是我的解决方案的示例代码

    enum READ_WRITE
    {
        READ,
        WRITE
    }
    public class Test
    {
        private static readonly object readWritelock = new object();
        public static object ReadWrite(READ_WRITE readWrite, object data)
        {
            object returnValue = 0;
            lock (readWritelock)
            {
                switch (readWrite)
                {
                    case READ_WRITE.READ :
                        //add you read code here
                        break;

                    case READ_WRITE.WRITE :
                        //add your write code here
                        break;
                }
            }
            return returnValue;
        }
    }