C# 如何在关闭应用程序之前等待异步事件完成?

C# 如何在关闭应用程序之前等待异步事件完成?,c#,C#,我正在构建一个爬虫程序,我正在使用它。这是一个非常好的系统:) 在开发过程中,我发现了一个问题,它与我想如何构建我的爬虫程序比aBot项目本身更相关,但我希望你能帮助我 在设置爬虫程序时,我指定爬虫完成时要调用的方法,有sync和async选项 crawler.PageCrawlCompleted += crawler_ProcessPageCrawlCompleted; crawler.PageCrawlCompletedAsync += crawler_Pro

我正在构建一个爬虫程序,我正在使用它。这是一个非常好的系统:) 在开发过程中,我发现了一个问题,它与我想如何构建我的爬虫程序比aBot项目本身更相关,但我希望你能帮助我

在设置爬虫程序时,我指定爬虫完成时要调用的方法,有sync和async选项

        crawler.PageCrawlCompleted += crawler_ProcessPageCrawlCompleted;
        crawler.PageCrawlCompletedAsync += crawler_ProcessPageCrawlCompleted;
我想使用异步url,因为这样我将在处理旧url的同时抓取另一个url。在我抓取最后一个url之前,这一切都很正常。 当我抓取最后一个时,我调用completeAsync方法,我的抓取程序工作完毕,因此它完成了,程序关闭,而没有完全完成对\u ProcessPageCrawlComplete方法的处理,因此我无法保证最后一个url会被处理

在关闭应用程序之前,我是否可以等待最后一个事件完成?这是一个设计缺陷吗

编辑:我忘了提到:我确实可以访问爬虫代码。我目前的解决方法是:如果链接是最后一个要处理的链接,那么创建一个WaitHandle并等待它完成。听起来有点乱,不过…

可以是一种解决方案:

在调用方法中:

//Declare the reset event
ManualResetEvent mre = new ManualResetEvent(false);

//Call the async method and subscribe to the event 
crawler.PageCrawlCompletedAsync += crawler_ProcessPageCrawlCompleted;

//The application will wait here until the mre is set.
mre.WaitOne();
在事件处理程序中:

private void crawler_ProcessPageCrawlCompleted(...)
{
   ....
   mre.Set();
}
另一种方法可以是。假设您需要抓取10页:

CountdownEvent countdown = new CountdownEvent (10);

//Subscribe to the event 
crawler.PageCrawlCompletedAsync += crawler_ProcessPageCrawlCompleted;

//Call 10 time the async method
....

//Wait for all events to complete
countdown.Wait();
在处理程序中:

private void crawler_ProcessPageCrawlCompleted(...)
{
    ....
   mre.Signal();
}
可以是一种解决方案:

在调用方法中:

//Declare the reset event
ManualResetEvent mre = new ManualResetEvent(false);

//Call the async method and subscribe to the event 
crawler.PageCrawlCompletedAsync += crawler_ProcessPageCrawlCompleted;

//The application will wait here until the mre is set.
mre.WaitOne();
在事件处理程序中:

private void crawler_ProcessPageCrawlCompleted(...)
{
   ....
   mre.Set();
}
另一种方法可以是。假设您需要抓取10页:

CountdownEvent countdown = new CountdownEvent (10);

//Subscribe to the event 
crawler.PageCrawlCompletedAsync += crawler_ProcessPageCrawlCompleted;

//Call 10 time the async method
....

//Wait for all events to complete
countdown.Wait();
在处理程序中:

private void crawler_ProcessPageCrawlCompleted(...)
{
    ....
   mre.Signal();
}

这可能过于简单化了,但你不能简单地保持打开爬虫的计数,在点击complete方法时减少该计数,并在该计数为0之前不关闭应用程序吗?不幸的是,爬虫将在获得最后一页的最后响应时完成“爬网”。因此,爬虫程序可能会关闭,但最后一个结果仍在处理中。这可能过于简单,但您不能简单地保留打开爬虫程序的计数,当您点击complete方法时减少该计数,并在该计数为0之前不关闭应用程序吗?不幸的是,爬虫程序将完成“爬网”当它获取最后一页的最后一个响应时。因此,爬虫程序可能会关闭,但最后的结果仍在处理中Hanks@Alberto这似乎是一个不错的方法,我将对此进行研究。但是如果我调用爬虫程序\u ProcessPageCrawlCompleted 10次,完成第一个处理将设置ManualResetEvent,然后不需要最后一个来完成应用程序。此语句正确吗?您应该仅在最后一个事件中调用mre.Set()。。。我在答案中添加了另一种方法。谢谢@Alberto,这似乎是一种很好的方法,我将对此进行研究。但是如果我调用爬虫程序\u ProcessPageCrawlCompleted 10次,完成第一个处理将设置ManualResetEvent,然后不需要最后一个来完成应用程序。此语句正确吗?您应该仅在最后一个事件中调用mre.Set()。。。我在答案中添加了另一种方法。