Reputation: 193
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 :
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.
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. This fixed the issue. I didn't tried the queue or Recative framework suggestions as this needed to be fixed quickly.
Upvotes: 2
Views: 530
Reputation: 117019
Microsoft's Reactive Framework would handle this nicely for you.
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:
var xmlreceiveds =
Observable
.FromEventPattern<EventHandler<MessageResponseEventArgs>>(
h => signalrClient.OnXMLReceived += h,
h => signalrClient.OnXMLReceived -= h)
.ObserveOn(Scheduler.Default);
Upvotes: 1
Reputation: 62248
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
.
Considering that Queue is FIFO structure, you will also maintain an order of the arrived XML
s, in case it's important to you.
Upvotes: 1
Reputation: 13960
"..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.
Upvotes: 1