[英]How to perform database operation independently?
我有1 exe
,它几乎不是Windows form
,它将在后台连续运行并watch my serial port
并且我有1个事件data receive event which fires as my serial port receive data
。
一旦在此事件中接收到数据,我就会将该数据传递给另一个事件处理程序, saves this data in database through web api method
事件处理程序saves this data in database through web api method
。
但是到串行端口的数据会经常出现,因此我想将此数据独立保存到数据库中,以便数据库插入操作不会阻止传入的串行端口数据。
这是我的代码:
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)//Fires as my serial port receives data
{
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
// Send data to whom ever interested
if (NewSerialDataRecieved != null)
{
NewSerialDataRecieved(this, new SerialDataEventArgs(data)); //pass serial port data to new below event handler.
}
}
void _spManager_NewSerialDataRecieved(object sender, SerialDataEventArgs e) //I want this event handler to run independently so that database save operation doenst block incoming serial port data
{
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;
}
//data is converted to text
string str = Encoding.ASCII.GetString(e.Data);
if (!string.IsNullOrEmpty(str))
{
//This is where i will save data to through my web api method.
RunAsync(str).Wait();
}
}
static async Task RunAsync(string data)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:33396/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(data);
var response = await client.PostAsJsonAsync<StringContent>("api/Service/Post", content);//nothing happens after this line.
}
}
Web API控制器:
public class MyController : ApiController
{
[HttpPost]
public HttpResponseMessage Post(HttpRequestMessage request)
{
var someText = request.Content.ReadAsStringAsync().Result;
return new HttpResponseMessage() { Content = new StringContent(someText) };
}
}
但是这里的问题是:
var response = await client.PostAsJsonAsync<StringContent>("api/Service/Post", content);
在该行之后,没有任何事情发生,这是该行上的操作块。
那么有人可以指导我吗?
从您的描述看来,您可能希望进行如下设置:1)Windows窗体侦听串行端口2)当有新内容要移植时,Windows Forms应用程序将其保存到某种队列中(msmq,for示例)3)您应该有单独的Windows服务来检查队列,并在队列中找到新消息时将请求发送到Web api
解决此问题的最佳方法是使用ConcurrentQueue。 只要在Google上进行搜索,您就会获得大量样品。 ConcurrentQueue是线程安全的,它支持从多个线程进行写入和读取。 因此,侦听海口端口的组件可以将数据写入队列。 而且,您可以有2个或多个并行运行的任务,它们监听此队列并在db接收到数据后立即对其进行更新。
不知道这是否是问题,但您不应阻止异步代码。 您正在执行RunAsync(str).Wait();
我相信这就是问题所在。 看看Stephen Cleary的这篇博客文章: http : //blog.stephencleary.com/2012/07/dont-block-on-async-code.html
我们独立地在SO C#聊天室中确定您的意思是“异步”。
您的解决方案是上面的代码,将这些数据保存到WebAPI端点,因此,对问题的任何解决方案都需要分两部分...
第1部分:客户部分
在客户端上,我们需要做的就是异步进行调用,以释放当前线程以继续在传入的串行端口上接收数据,我们可以这样做...
// build the api client, you may want to keep this in a higher scope to avoid recreating on each message
var api = new HttpClient();
api.BaseAddress = new Uri(someConfigVariable);
// asynchronously make the call and handle the result
api.PostAsJsonAsync("api/My", str)
.ContinueWith(t => HandleResponseAsync(t.Result))
.Unwrap();
...
第二部分:服务器部分
由于您具有网络API,因此我也将假设您也使用EF,因此,通常的,“干净的”方式可以做到这一点,并且去除了所有其他功能(例如模型验证/错误处理),看起来像.. 。
// in your EF code you will have something like this ...
Public async Task<User> SaveUser(User userModel)
{
try
{
var newUser = await context.Users.AddAsync(userModel);
context.SavechangesAsync();
return newUser;
}
catch(Exception ex) {}
}
// and in your WebAPI controller something like this ...
HttpPost]
public async Task<HttpResponseMessage> Post(User newUser)
{
return Ok(await SaveUser(newUser));
}
...
免责声明:
这里涉及的概念要深入得多,正如我上面所暗示的,这里已经遗漏了很多东西,例如验证,错误检查等,但这是使用我相信您正在使用的技术将串行端口数据输入数据库的核心。
对于任何想要实现这种目标的人来说,重要的事情可能包括:任务,事件处理,WebAPI,EF,异步操作,流。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.