等待事件在再次被解雇之前完成

时间:2014-03-18 11:39:58

标签: c# asynchronous async-await

我有以下场景,我有一个事件继续接收需要被推入DB的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))
   }
}

问题是,当我在save方法中遇到第一个等待时,控件被带回到接收新xml的事件并再次调用save,所以我的问题是,我如何确保执行事件再次被触发之前,save方法中的所有代码。

当它被调用时我无法控制该事件,但是当它调用时我想确保在下次调用它之前完全处理该事件,我该怎么办?

更新:感谢大家的回复,我之所以想要在再次被解雇之前完全处理该事件的原因是,如果我再获得一个与事件中的第一个类似的xml,我实际上是插入两个由于异步性质,这将导致DB中的重复条目,最后我重新排序了我的保存并检查了在等待保存方法之前是否存在重复。这解决了这个问题。我没有尝试过队列或Recative框架建议,因为这需要快速修复。

3 个答案:

答案 0 :(得分:1)

“..我想确保在下次调用之前完全处理事件,我该怎么做?”

不要让异步方法符合你的要求。

答案 1 :(得分:1)

您需要在事件处理程序中使用Queue,在其中推送到达的XML,并且您需要一个计时器,在每个刻度线上,您从该队列中获取一个元素并将其保存到{{ 1}}。

考虑到Queue是FIFO结构,您还将维护已到达DB的订单,以防它对您来说很重要。

答案 2 :(得分:1)

Microsoft的Reactive Framework可以很好地为您处理。

不是以正常方式处理事件,而是从事件中创建一个observable:

var xmlreceiveds =
    Observable.FromEventPattern<EventHandler<MessageResponseEventArgs>>(
        h => signalrClient.OnXMLReceived += h, 
        h => signalrClient.OnXMLReceived -= h);

现在,您可以获得稳定的事件流,保证在下一个事件发生之前完成。

你这样处理:

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));
    }
});

您可以通过包含ObserveOn方法调用轻松地在不同的线程上处理它,如下所示:

var xmlreceiveds =
    Observable
        .FromEventPattern<EventHandler<MessageResponseEventArgs>>(
            h => signalrClient.OnXMLReceived += h, 
            h => signalrClient.OnXMLReceived -= h)
        .ObserveOn(Scheduler.Default);