简体   繁体   English

System.Threading.Timer内部的方法

[英]Method inside System.Threading.Timer

I have a method in a web server application that runs a few mysql queries every x minutes in the background, I searched a good way to do it and came across the System.Threading.Timer class. 我有一个Web服务器应用程序中的方法,该方法在后台每x分钟运行一些mysql查询,我搜索了一种很好的方法来执行此操作,并遇到了System.Threading.Timer类。 I managed to code the method inside and using a log I'm keeping track of it's execution (each query and each exception) but I'm facing a problem that I still cannot understand what's happening, the thing is when the method needs to actually do something (when I have a new record on my application the method will grab it's data and start writing it on my database but it will only do that if at that x minute it runs the data is there otherwise it will just run doing nothing) it stops, there is no exception on either the queries or the thread, I just check the log and at the x minute it should be writing something on it there is simply nothing, something just kills my thread and I can't understand what/why, if anyone can help me I would appreciante (sorry my bad english), here is the code snippet: 我设法在内部编写了该方法的代码,并使用日志跟踪了它的执行情况(每个查询和每个异常),但是我遇到了一个问题,我仍然无法理解正在发生的事情,问题是该方法何时需要实际做某事(当我在应用程序上有一条新记录时,该方法将获取它的数据并开始将其写入我的数据库中,但是只有在那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;
                }
            }

The using statement will close the StreamWriter too quickly. using语句将太快关闭StreamWriter。 In fact it will close the StreamWriter right after after the new timer is setup. 实际上,它将在设置新计时器后立即关闭StreamWriter。

So the timer won't be able to write to the log when the timer fires with it coded this way. 因此,以这种方式编码的计时器启动时,计时器将无法写入日志。

You will need to move the using statement that setups up sw into the autonomous method the timer executes. 您需要将设置swusing语句移到计时器执行的自主方法中。

This should work better for you. 这应该对您更好。

 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

Also in setting up the timer I'm not sure that TimeSpan.FromMinutes(2) will work for you. 同样在设置计时器时,我不确定TimeSpan.FromMinutes(2)是否适合您。 I believe based on this code example: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/threading/thread-timers that the last parameter is in milliseconds. 我相信基于以下代码示例: https : //docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/threading/thread-timers上一个参数以毫秒为单位。 So 120000 is what you are looking for. 因此,您要寻找的是120000。

Additional Things to Consider 需要考虑的其他事项
While the above code will "work" it suffers from a serious issue which @Mukesh eludes to in his answer/suggestion. 虽然上面的代码将“起作用”,但它遇到了一个严重的问题,@ Mukesh在其答案/建议中未曾提及。 If a background process throws an exception it will take down the IIS app pool process and force the web app to recycle. 如果后台进程引发异常,它将关闭IIS应用程序池进程并强制Web应用程序回收。 This is almost never desirable. 这几乎是永远不可取的。 And the way the above code is written is such that any exception in the timer proc is gonna cause that to happen since after catching an exception and logging them, it rethrows them. 上面代码的编写方式使得计时器proc中的任何异常都将导致该异常的发生,因为在捕获到异常并将其记录下来之后,它会将它们重新抛出。 Serious thought should be given to using a 3rd party background scheduler as mentioned in his answer/suggestion, or at the very least it'd be good ensure that no exception escapes from the timer proc like so: 应当认真考虑使用他的回答/建议中提到的第三方后台调度程序,或者至少要确保没有任何异常从计时器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

I am just giving you a advice :). 我只是给你一个建议:)。 You should not do background job in web application, In IIS web server, application might go into sleep mode or during worker process recycling your background task will not get executed. 您不应该在Web应用程序中执行后台作业。在IIS Web服务器中,应用程序可能会进入睡眠模式,或者在回收工作进程期间,您的后台任务将无法执行。 Instead of this you can integrate library build specifically to achieve background jobs such as Hangfire , FLUENTSCHEDULER etc. which comes with pretty good dashboard functionality too. 取而代之的是,您可以集成专门构建的库来实现后台作业,例如HangfireFLUENTSCHEDULER等,它们也具有非常好的仪表板功能。

Please see below great article for that matter. 为此,请参阅以下精彩文章。 How to run Background Tasks in ASP.NET 如何在ASP.NET中运行后台任务

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

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