C# 套接字:接收和发送之间的延迟(WriteStream.WriteAsync()和ReadStream.ReadAsync())
如何正确实现使用WriteStream.WriteAsync()发送字符串和使用ReadStream.ReadAsync()等待响应之间的延迟 我使用rda.SocketsForPCL插件创建TCP客户端套接字,然后创建相应的读写流 当我使用TimeSpan.From毫秒(200))实现延迟时,我得到一个System.NullReferenceException:Object reference未设置为VS 2017中对象的实例。我是C#和Xamarin的新手,我不确定除了上述方法之外如何实现一个不会导致抛出异常的延迟 是否有一个“全局”异常处理程序可以以某种方式实现,以处理诸如VS 2017这样的异常,因为VS 2017不会破坏代码,并准确地向您显示异常实际发生的位置 我已经在Xamarin.Forms中实现了下面的活动页面,但它不允许我使用TimeSpan.frommilluses(200))实现延迟在下面的UpdateUserDataAsync()函数中注释:C# 套接字:接收和发送之间的延迟(WriteStream.WriteAsync()和ReadStream.ReadAsync()),c#,sockets,xamarin,xamarin.forms,exception-handling,C#,Sockets,Xamarin,Xamarin.forms,Exception Handling,如何正确实现使用WriteStream.WriteAsync()发送字符串和使用ReadStream.ReadAsync()等待响应之间的延迟 我使用rda.SocketsForPCL插件创建TCP客户端套接字,然后创建相应的读写流 当我使用TimeSpan.From毫秒(200))实现延迟时,我得到一个System.NullReferenceException:Object reference未设置为VS 2017中对象的实例。我是C#和Xamarin的新手,我不确定除了上述方法之外如何实现一
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
//
++++++++++++++++++++++++++++++++++++++++++++++++
}
公共输入页()
{
尝试
{
初始化组件();
}
捕获(例外情况除外)
{
字符串错误=例如消息;
投
}
client=SharedSocket.Instance().getSocket();//获取持久套接字==>客户端连接
UpdateUserDataAsync();//用于更新Listview的内容
loadSampleData();//加载ListView中的项
BindingContext=这个;
this.BindingContext=new relay();//绑定Listview项
var neg=lstView.BindingContext作为中继;
InputID=neg.ID;
}
私有异步void UpdateUserDataAsync()//请求和接收控制器名称
{
byte[]rv=新字节[]{0x01,0x01,0x01,0x01,0x01,0x01};//请求
Send_CntrP(rv);//发送请求
//等待任务延迟(时间跨度从毫秒(200));
rec2=等待接收字节();
}//UpdateUserDataAsync
私有void loadSampleData()
{
ObservableCollection lisInputs=新的ObservableCollection();
如果(rec2.Length>=4)
{
byte[]states=Encoding.ASCII.GetBytes(rec2);//创建接收字符串的字节数组
对于(int j=6;j=1&&rec2.长度<30)
{
return wait Task.FromResult(rec2);//返回字符串
}
其他的
{
//等待显示警报(“错误”,“接收消息时出错”,“确定”);
XFToast.ShortMessage(“接收消息时出错。\n\r请验证连接。”);//Android本机Toast消息
返回“ERROR”;//返回“ERROR”消息
}
}//阅读反应
}//客户
其他的
{
return err;//当没有可用的连接时,返回“Connection Error”字符串
}
返回rec2;//以字符串形式返回接收到的字节
}//接收字节
//
++++++++++++++++++++++++++++++++++++++++++++++++
}
我很抱歉写了这么长的文章,但我已经为这个问题挣扎了一段时间,我没有足够的经验处理所有异步方法和异常“查找”,然后处理VS 2017和Xamarin,因为我仍在学习基础知识:(
提前感谢您的帮助/建议。这是我的解决方案的示例代码
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;
}
}
我通常将读写代码放在同一个锁中,这样一次只能发生一个。然后,你永远不会同时执行读写操作,你总是在读之前等待写操作完成。@jdweng,我如何将它们放在同一个锁(或块)中正如你所提到的?谢谢,我会尝试在我的代码中实现这一点。我仍然无法实现发送和接收之间的延迟;当我发送和调用接收时,它会读取一堆零。这可能是因为它试图读取接收到的消息太快了吗?我对xamarin了解不够,无法给出答案,但我知道Databasee架构非常好。您基本上有一个数据库,问题是该数据库设计用于处理共享事务。共享数据库包含锁定方法,确保您没有冲突。如果您有一个包含10个项目的数据库,而一个客户同时购买9个项目,而另一个客户需要5个项目。2n是什么d客户获取?设计用于共享第二个客户获取1项的数据库。不设计用于共享的数据库为第二个客户提供5项(4项不存在)。