如何独立执行数据库操作
本文关键字:执行 执行数 数据库 操作 独立 何独立 | 更新日期: 2024-10-23 10:11:22
我有1 exe
,它完全不是Windows form
,它将在后台连续运行,并且watch my serial port
和我有一个事件data receive event which fires as my serial port receive data
。
一旦我收到此事件中的数据,我就会将此数据传递给另一个事件处理程序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);
这一行之后没有发生任何操作块。
有人能指导我吗?
我们在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();
第2部分:服务器部分
既然你有web 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、异步操作、流。
根据您的描述,您可能想要这样的设置:1) windows窗体侦听串行端口2) 当新的东西进入端口时,windows窗体应用程序会将其保存到某种队列(例如msmq)中3) 您应该有一个单独的windows服务来检查队列,当它在队列中发现新消息时,它会向web api 发送请求
此问题的最佳解决方案是使用ConcurrentQueue。只要在谷歌上搜索一下,你就会得到大量的样品。ConcurrentQueue是线程安全的,它支持从多个线程进行写入和读取。因此,侦听searal端口的组件可以将数据写入队列。您可以有两个或多个并行运行的任务,它们监听这个队列,并在数据库接收到数据后立即更新数据库。
不确定这是否是问题所在,但不应该阻塞异步代码。你在做RunAsync(str).Wait();
,我认为这就是问题所在。看看Stephen Cleary的这篇博客文章:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html