问题描述
我们使用自定义构建的 C# 应用程序(“communicator”)与其他几个本地安装的应用程序(Excel,...)进行交互。通信器从队列中获取其输入,按定义的顺序调用应用程序(通过多个 DLL,再次自定义构建)来处理输入并将结果提交到队列。完成步骤所需的时间可以预测(步骤 1 (app1) 在 10 秒内完成,步骤 2 (app2) 在 45 秒内完成等),处理单个订单的总时间不应超过 90 秒。>
大多数情况下,事情在无人看管的情况下运行良好(按照设计),但有时一个被调用的应用程序会卡住,如果没有人工交互就无法继续。这也会停止队列处理。我们会调查原因并尝试消除它们 - 一旦检测到中断。
我们首先想减少检测中断的时间 - 也许通过使用通信器或其他方法来检测已超过完成步骤的预期时间并通知管理员这种情况(发送电子邮件) .
您是否会使用通信器在每个步骤设置一个计时器,然后在超过预期完成时间(并从其代码中发送电子邮件)时引发错误,或者在步骤开始时调用外部应用程序及其完成并让它完成计时和通知部分以避免阻塞通信器代码?
您是否可以分享一些用于计时和发送电子邮件的代码示例? 或者,也许建议一个外部应用程序,它可以接受来自通信器的启动信号并在特定时间范围内未收到完成消息时发送电子邮件?
最好的问候
解决方法
我最初是作为评论回答的,但我想我也可以做一个正确的回答。
你如何做到这一点将取决于很多事情。我正在简化,因为我不知道您的代码实际上是什么样子。
以下是代码的基本轮廓:
private async Task ExecuteStepInCommunicator(TimeSpan expectedTimeToComplete)
{
// Maybe you want to allow for some buffer as @Oakley suggested.
// This will give it twice as long as the expected time to complete.
expectedTimeToComplete = expectedTimeToComplete.Add(expectedTimeToComplete);
using var alertTimer = new Timer()
{
Interval = expectedTimeToComplete.TotalMilliseconds,AutoReset = false,};
alertTimer.Elapsed += this.AlertTimer_Elapsed;
// Replace the Task.Delay with your normal 'Communicator' logic
await Task.Delay(1000);
// Make sure the timer is stopped once your logic has finished.
// If it hasn't run yet,no alert will be sent. If it has run this will do nothing
alertTimer.Stop();
}
private void AlertTimer_Elapsed(object sender,ElapsedEventArgs e)
{
// Send email from here. This will be called only once,when the timer elapses.
// https://docs.microsoft.com/en-us/dotnet/api/system.net.mail.smtpclient.send?view=net-5.0
}
System.Timer
不会阻止您的正常代码运行。计时器结束后,Elapsed 回调将在线程池中的线程上运行,因此即使您的通信器代码也在运行,它也可以运行。
因为这很简单,所以我建议将它放在同一个地方。您建议发送到其他一些应用程序来执行计时和通知,但这会增加很多复杂性(并且有可能出错),而且收益甚微。