C# 当到达串行端口的数据是异步的时,如何通过web服务存储数据?

C# 当到达串行端口的数据是异步的时,如何通过web服务存储数据?,c#,winforms,asp.net-web-api,concurrency,serial-port,C#,Winforms,Asp.net Web Api,Concurrency,Serial Port,我在用户的桌子上“安装”了一台设备(一张桌子只不过是一把椅子或一张桌子,用户可以坐在上面),我将支持数千张桌子 用户将拥有一个“芯片”,用户将在安装在桌面上的设备上扫描该芯片 该设备将读取芯片上的数据,并将其发送到我的笔记本电脑,笔记本电脑也将安装其中一个设备,但该设备是负责收集所有用户扫描芯片数据的主要设备 所有数据都将通过wifi路由器路由到我的设备,我将从我的主设备收听这些数据,并通过串行端口连接从笔记本电脑读取这些数据 当每个用户号扫描他/她的芯片时,就会发送数据 我已经创建了一个win

我在用户的桌子上“安装”了一台设备(一张桌子只不过是一把椅子或一张桌子,用户可以坐在上面),我将支持数千张桌子

用户将拥有一个“芯片”,用户将在安装在桌面上的设备上扫描该芯片

该设备将读取芯片上的数据,并将其发送到我的笔记本电脑,笔记本电脑也将安装其中一个设备,但该设备是负责收集所有用户扫描芯片数据的主要设备

所有数据都将通过wifi路由器路由到我的设备,我将从我的主设备收听这些数据,并通过串行端口连接从笔记本电脑读取这些数据

当每个用户号扫描他/她的芯片时,就会发送数据

我已经创建了一个windows窗体应用程序,它将在我的笔记本电脑上的后台持续运行,并将监听连接主设备的串行端口

这是我在这里的代码::

public分部类MainUI:Form
{
SerialPortManager\u spManager;
公共MainUI()
{
初始化组件();
用户初始化();
}
}
私有void UserInitialization()
{
_spManager=新的SerialPortManager();
_spManager.newserialdatareceived+=新事件处理程序(\u spManager\u newserialdatareceived);
this.FormClosing+=新FormClosingEventHandler(MainUI\u FormClosing);
}
私有void mainu_加载(对象发送方、事件参数)
{
_spManager.StartListening()
}
void\u serialPort\u DataReceived(对象发送方,SerialDataReceivedEventArgs e)
{
int dataLength=_serialPort.BytesToRead;
字节[]数据=新字节[dataLength];
int nbrDataRead=_serialPort.Read(数据,0,数据长度);
如果(nbrDataRead==0)
返回;
//向感兴趣的人发送数据
如果(NewSerialDataReceived!=null)
{
NewSerialDataReceived(这是新的SerialDataEventArgs(数据));
}
}
void\u spManager\u newserialDataReceived(对象发送方,SerialDataEventArgs e)
{
if(this.invokererequired)
{
//使用此.Invoke会在关闭串行端口时导致死锁,无论如何,BeginInvoke是一种很好的做法。
this.BeginInvoke(新事件处理程序(_spManager_newserialdatareceived),新对象[]{sender,e});
返回;
}
//数据被转换成文本
string str=Encoding.ASCII.GetString(e.Data);
如果(!string.IsNullOrEmpty(str))
{
//在这里,我将通过web服务将这些数据存储到我的数据库中。
//无论是WCF服务还是Web Api,我都应该使用什么,因为数据将是连续的,就像在同一时间一样
//时间超过10或100个用户可以同时扫描数据,因此此事件将连续触发。
//我正在使用实体框架将数据存储到数据库中,以及如何同步调用web服务来存储数据
//这样我的呼叫就不会阻塞串行端口的传入数据
}
}
我主要关心的是,我将有许多用户同时扫描数据,以及当超过10或100个用户同时扫描数据时,我将如何处理


如何缓解此潜在问题?

关闭串行端口,每隔一段时间加载一次。经过一段时间后,打开端口并扫描所有设备,然后再次关闭

        public void MainUI.Load(Object sender, Eventargs e)
        {
            if (_spmanager != null && !_spManager.IsOpen)
                //*write the code here where it opens and starts listening
                _spmanager.StartListening();
                //*write the code here where it waits a little bit then 
                _spmanager.Close();
 }
因此,每次加载时,它都会在端口关闭时启动,它会打开一点,扫描所有为真的值,然后再次关闭


我不是很确定,但这只是一个如何处理它的想法。代码可能不准确或不正确,我只是写得很快。从这个想法来看

好吧,如果我答对了问题,你需要这样做

  void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int dataLength = _serialPort.BytesToRead;
            byte[] data = new byte[dataLength];
            int nbrDataRead = _serialPort.Read(data, 0, dataLength);
            if (nbrDataRead == 0)
                return;

            // Send data to api
            string str = Encoding.ASCII.GetString(e.Data);
                if (!string.IsNullOrEmpty(str))
                {
                      var api = new HttpClient();
                      api.BaseUrl("http://somewhere.com");
                      api.PostAsJsonAsync("api/Something", str)
                }

            if (this.InvokeRequired)
            {
                // Using this.Invoke causes deadlock when closing serial port,
                // and BeginInvoke is good practice anyway.
                this.BeginInvoke(new EventHandler<SerialDataEventArgs>(
                    _spManager_NewSerialDataRecieved), new object[] { sender, e
                });
                return;
            }
        }


// i think this can go completely ...
void _spManager_NewSerialDataRecieved(object sender, SerialDataEventArgs e)
void\u serialPort\u DataReceived(对象发送方,SerialDataReceivedEventArgs e)
{
int dataLength=_serialPort.BytesToRead;
字节[]数据=新字节[dataLength];
int nbrDataRead=_serialPort.Read(数据,0,数据长度);
如果(nbrDataRead==0)
返回;
//向api发送数据
string str=Encoding.ASCII.GetString(e.Data);
如果(!string.IsNullOrEmpty(str))
{
var api=新的HttpClient();
api.BaseUrl(“http://somewhere.com");
api.PostAsJsonAsync(“api/Something”,str)
}
if(this.invokererequired)
{
//使用此.Invoke会在关闭串行端口时导致死锁,
//不管怎样,BeginInvoke是一种很好的实践。
this.BeginInvoke(新的EventHandler(
_spManager_newserialDataReceived),新对象[]{sender,e
});
返回;
}
}
//我想这完全可以。。。
void\u spManager\u newserialDataReceived(对象发送方,SerialDataEventArgs e)

将数据发布到webapi,但在另一个线程上进行发布时,串行端口可以继续接收数据

我的数据将持续出现在data received事件中,因此对于我要保存在数据库中的每个数据,但当我将数据保存在数据库中时,可能会再次触发我的data received事件。那又如何我想让我的数据库保存操作独立
  void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int dataLength = _serialPort.BytesToRead;
            byte[] data = new byte[dataLength];
            int nbrDataRead = _serialPort.Read(data, 0, dataLength);
            if (nbrDataRead == 0)
                return;

            // Send data to api
            string str = Encoding.ASCII.GetString(e.Data);
                if (!string.IsNullOrEmpty(str))
                {
                      var api = new HttpClient();
                      api.BaseUrl("http://somewhere.com");
                      api.PostAsJsonAsync("api/Something", str)
                }

            if (this.InvokeRequired)
            {
                // Using this.Invoke causes deadlock when closing serial port,
                // and BeginInvoke is good practice anyway.
                this.BeginInvoke(new EventHandler<SerialDataEventArgs>(
                    _spManager_NewSerialDataRecieved), new object[] { sender, e
                });
                return;
            }
        }


// i think this can go completely ...
void _spManager_NewSerialDataRecieved(object sender, SerialDataEventArgs e)