[英]Awaiting an event to complete before it gets fired again
I have the following scenario, I have an event that keeps on receiving xml's that need to be pushed into DB, the pushing code and event looks something like below : 我有以下情况,我有一个继续接收需要推送到数据库的xml的事件,推送代码和事件如下所示:
async void signalrClient_OnXMLReceived(object value, MessageResponseEventArgs e)
{
await SaveXML();
}
async task SaveXML(string xmlDoc)
{
await SaveCustomer(GetCustomerDataFrmXML(xmlDoc));
await SavePlantInfo(GetPlantDataFrmXML(xmlDoc))
if(NotJobexists(GetJob(xmlDoc))
{
await SaveJob(GetJobInfo(xmlDoc))
}
}
The problem is as soon as I encounter the first await in the save method, the control is taken back to the event where it receives new xml and calls save again, so My question is , how do I make sure that I execute all the code in the save method before the event gets fired again. 问题是我在save方法中遇到第一次等待时,该控件立即返回到它接收新xml并再次调用save的事件,所以我的问题是,如何确保执行所有代码在事件再次触发之前在save方法中单击。
I do not have control over the event when it gets called, but as and when it calls I want to make sure that I handle the event fully before it gets called next time, how can I do it? 调用该事件时,我无法控制该事件,但是在调用该事件时,我想确保在下次调用该事件之前完全处理该事件,该怎么办?
UPDATE : Thanks all for your reply, The reason why I wanted to handle the event fully before it gets fired again is, if I get one more xml which is similar to the first one in the event, I was actually inserting both which will cause the duplicate entries in DB due to the async nature, finally I reordered my saves and checked if duplicate exists before couple of await save methods. 更新:感谢您的答复,我想在再次触发该事件之前完全处理该事件的原因是,如果我又得到一个与事件中的第一个类似的xml,则实际上我插入了这两个都会导致由于异步性质,数据库中的重复项最终被重新排序,并在等待存储方法之前检查是否存在重复项。 This fixed the issue. 这解决了问题。 I didn't tried the queue or Recative framework suggestions as this needed to be fixed quickly. 我没有尝试过队列或Recative框架建议,因为这需要快速解决。
"..I want to make sure that I handle th event fully before it gets called next time, how can I do it?" “ ..我想确保在下次调用该事件之前能完全处理该事件,我该怎么办?”
Don't make async the method at all should meet your requirement. 根本不要使方法完全符合您的要求。
You need a Queue in the event handler, where you push XML
that arrives, and you need a timer, where on every tick you get an element from that queue and save it to DB
. 您需要在事件处理程序中添加一个队列 ,在其中推送到达的XML
,并需要一个计时器,在每个滴答声中,您从该队列中获取一个元素并将其保存到DB
。
Considering that Queue is FIFO structure, you will also maintain an order of the arrived XML
s, in case it's important to you. 考虑到Queue是FIFO结构,如果对您很重要,您还将维护到达的XML
的顺序 。
Microsoft's Reactive Framework would handle this nicely for you. Microsoft的Reactive Framework将为您很好地处理此问题。
Instead of handling events in the normal way you create an observable from the event: 您可以从事件中创建一个可观察对象,而不必以常规方式处理事件:
var xmlreceiveds =
Observable.FromEventPattern<EventHandler<MessageResponseEventArgs>>(
h => signalrClient.OnXMLReceived += h,
h => signalrClient.OnXMLReceived -= h);
You can now get a steady stream of events that are guaranteed to complete before the next event comes. 现在,您可以获得源源不断的事件,这些事件一定会在下一个事件发生之前完成。
You handle then like this: 您可以这样处理:
var xmlreceiveds =
Observable
.FromEventPattern<EventHandler<MessageResponseEventArgs>>(
h => signalrClient.OnXMLReceived += h,
h => signalrClient.OnXMLReceived -= h);
xmlreceiveds.Subscribe(ep =>
{
SaveCustomer(GetCustomerDataFrmXML(ep.EventArgs.XmlDoc));
SavePlantInfo(GetPlantDataFrmXML(ep.EventArgs.XmlDoc));
if (NotJobexists(GetJob(ep.EventArgs.XmlDoc)))
{
SaveJob(GetJobInfo(ep.EventArgs.XmlDoc));
}
});
You can easily make this be handled on a different thread by including an ObserveOn
method call, like so: 通过包括一个ObserveOn
方法调用,可以轻松地在另一个线程上处理此问题,如下所示:
var xmlreceiveds =
Observable
.FromEventPattern<EventHandler<MessageResponseEventArgs>>(
h => signalrClient.OnXMLReceived += h,
h => signalrClient.OnXMLReceived -= h)
.ObserveOn(Scheduler.Default);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.