繁体   English   中英

System.Threading.Timer内部的方法

[英]Method inside System.Threading.Timer

我有一个Web服务器应用程序中的方法,该方法在后台每x分钟运行一些mysql查询,我搜索了一种很好的方法来执行此操作,并遇到了System.Threading.Timer类。 我设法在内部编写了该方法的代码,并使用日志跟踪了它的执行情况(每个查询和每个异常),但是我遇到了一个问题,我仍然无法理解正在发生的事情,问题是该方法何时需要实际做某事(当我在应用程序上有一条新记录时,该方法将获取它的数据并开始将其写入我的数据库中,但是只有在那x分钟运行了数据的情况下,它才会这样做,否则它将什么也不做)它停止了,查询或线程上都没有异常,我只是检查了日志,在x分钟内它应该在上面写了一些东西,根本什么也没有,有些东西扼杀了我的线程,我不明白什么/为什么,如果有人可以帮助我,我会感谢(抱歉我的英语不好),这是代码段:

 using (StreamWriter sw = File.AppendText(path + @"\log_test.txt")) {
                sw.WriteLineAsync("-------- LOG BEGIN --------" + Environment.NewLine);
                try {
                    var timer = new System.Threading.Timer(async (ev) => {
                        bool sync = await AzureSync.Begin();
                    }, null, TimeSpan.Zero, TimeSpan.FromMinutes(2));
                }
                catch (Exception ex) {
                    sw.WriteLine(DateTime.Now + "**** ERROR ****" + Environment.NewLine);
                    sw.WriteLine(ex.ToString() + Environment.NewLine);
                    throw ex;
                }
            }

using语句将太快关闭StreamWriter。 实际上,它将在设置新计时器后立即关闭StreamWriter。

因此,以这种方式编码的计时器启动时,计时器将无法写入日志。

您需要将设置swusing语句移到计时器执行的自主方法中。

这应该对您更好。

 var timer = new System.Threading.Timer(async (ev) => {

     using (StreamWriter sw = File.AppendText(path + @"\log_test.txt")) {
           sw.WriteLineAsync("-------- LOG BEGIN --------" + Environment.NewLine);
            try {
                bool sync = await AzureSync.Begin();
            }
            catch (Exception ex) {
                sw.WriteLine(DateTime.Now + "**** ERROR ****" + Environment.NewLine);
                sw.WriteLine(ex.ToString() + Environment.NewLine);
                throw ex;
            }
        }
 }, null, TimeSpan.Zero, 120000);   //120000 milliseconds is 2 Minutes

同样在设置计时器时,我不确定TimeSpan.FromMinutes(2)是否适合您。 我相信基于以下代码示例: https : //docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/threading/thread-timers上一个参数以毫秒为单位。 因此,您要寻找的是120000。

需要考虑的其他事项
虽然上面的代码将“起作用”,但它遇到了一个严重的问题,@ Mukesh在其答案/建议中未曾提及。 如果后台进程引发异常,它将关闭IIS应用程序池进程并强制Web应用程序回收。 这几乎是永远不可取的。 上面代码的编写方式使得计时器proc中的任何异常都将导致该异常的发生,因为在捕获到异常并将其记录下来之后,它会将它们重新抛出。 应当认真考虑使用他的回答/建议中提到的第三方后台调度程序,或者至少要确保没有任何异常从计时器proc中逃脱,如下所示:

 var timer = new System.Threading.Timer(async (ev) => {
     try{
          using (StreamWriter sw = File.AppendText(path + @"\log_test.txt")) {
                sw.WriteLineAsync("-------- LOG BEGIN --------" + Environment.NewLine);
                 try {
                     bool sync = await AzureSync.Begin();
                 }
                 catch (Exception ex) {
                     sw.WriteLine(DateTime.Now + "**** ERROR ****" + Environment.NewLine);
                     sw.WriteLine(ex.ToString() + Environment.NewLine);
                 }
             }
      }catch{}; //swallow exception and prevent it from taking down the process/IIS app pool
 }, null, TimeSpan.Zero, 120000);   //120000 milliseconds is 2 Minutes

我只是给你一个建议:)。 您不应该在Web应用程序中执行后台作业。在IIS Web服务器中,应用程序可能会进入睡眠模式,或者在回收工作进程期间,您的后台任务将无法执行。 取而代之的是,您可以集成专门构建的库来实现后台作业,例如HangfireFLUENTSCHEDULER等,它们也具有非常好的仪表板功能。

为此,请参阅以下精彩文章。 如何在ASP.NET中运行后台任务

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM