Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 防止计时器在控制台应用程序中被垃圾收集_C#_Timer_Garbage Collection_Console Application - Fatal编程技术网

C# 防止计时器在控制台应用程序中被垃圾收集

C# 防止计时器在控制台应用程序中被垃圾收集,c#,timer,garbage-collection,console-application,C#,Timer,Garbage Collection,Console Application,总之,我正在监视outlook收件箱中的一些电子邮件,并根据内容进行分析。我通过运行控制台应用程序并触发计时器来实现这一点,如下所示。问题是这会在一段时间后被垃圾收集,我必须手动重新启动应用程序。我无法在windows服务中运行此操作,因为调用Outlook api时遇到一些权限问题。请看下面我的代码 我尝试对计时器对象执行GC.SuppressFinalize()、GC.KeepAlive(),但没有效果 class Program { private stati

总之,我正在监视outlook收件箱中的一些电子邮件,并根据内容进行分析。我通过运行控制台应用程序并触发计时器来实现这一点,如下所示。问题是这会在一段时间后被垃圾收集,我必须手动重新启动应用程序。我无法在windows服务中运行此操作,因为调用Outlook api时遇到一些权限问题。请看下面我的代码

我尝试对计时器对象执行GC.SuppressFinalize()、GC.KeepAlive(),但没有效果

    class Program
    {
       private static System.Timers.Timer _timer = new System.Timers.Timer();
       static void Main(string[] args)
        {


            _timer.Interval = 10000;            
            _timer.Start();
            _timer.Elapsed += Timer_Elapsed1;

            Console.ReadLine();
        }
    }


        private static void Timer_Elapsed1(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                _timer.Stop();                
                AddNumbers(2, 2);
                Console.WriteLine("The current time now is :{0}", DateTime.Now.ToString());
                GC.SuppressFinalize(_timer);                
                _timer.Start();

            }
            catch (Exception ex)
            {
                _timer.Start();
                Console.WriteLine("Timer restarted from exception");
            }
            finally
            {
                _timer.Start();
            }

        }
private static void AddNumbers(int x, int y)
        {
            var sum = x + y;
            Console.WriteLine(sum);
        }

在示例应用程序的范围内,
计时器
未被垃圾收集,因此您一定遇到了另一个错误。另外,请参阅我下面关于
GC.SuppressFinalize
的说明和示例,因为您所暗示的和它所做的是两件不同的事情

循环而非计时器

只是一个建议:当使用
计时器
并且
已运行
事件调用计时器停止,然后在完成后再次启动时,这是一个迹象,您需要使用线程等待来运行一个简单的循环

由于这是一个控制台应用程序,并且不需要其他线程,因此我将发布一个简单的循环示例,在IMO中,该示例将更高效、更易于管理

using System;
using System.Threading;

namespace Question_Answer_Console_App
{
    class Program
    {
        private const int SleepTimeMS = 10000;
        static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback((state) =>
            {
                while (true)
                {
                    Thread.Sleep(SleepTimeMS);
                    AddNumbers(2, 2);
                    Console.WriteLine("The current time now is :{0}", DateTime.Now.ToString());
                }
            }));

            Console.Read();
        }

        private static void AddNumbers(int x, int y)
        {
            var sum = x + y;
            Console.WriteLine(sum);
        }
    }
}
GC.com信息

而且,
GC.SuppressFinalize
与垃圾收集没有任何关系;它只是告诉垃圾收集器,在收集时,不要在对象上运行终结器(C#中的析构函数方法)。当有已处理的项目并且您不想复制工作时,这非常有用。。。例如,如果您的对象是
IDisposable
,并且您将
Dispose
方法放置在析构函数中,并且用户在使用时正确地处理了它,那么您可能希望跳过析构函数。下面是一个正确使用
GC.SuppressFinalize
的示例

public class SomethingDisposable : IDisposable
{
    public void Dispose()
    {
        //Dispose of some unmanaged resources or something.
        GC.SuppressFinalize(this); //We can safely skip the Destructor method (Finalizer)
    }

    ~SomethingDisposable() => Dispose(); //Just incase the object is garbage collected and never properly disposed.
}
GC.com示例

这里有一个控制台应用程序,演示了工作中的
GC.SuppressFinalize
。我使2个
IDisposable
对象。第一个我用
using
语句正确地处理了,第二个我没有。一旦它们超出范围,就要进行垃圾收集。我故意调用垃圾收集器,并等待调用所有终结器,以便立即看到结果

请注意,disposed对象不调用终结器,而未disposed对象调用终结器(这反过来调用dispose…,这是实现它的正确方法)

输出:

Testing Disposable-Test
Disposed Disposable-Test

Testing Finalizing-Test
Finalized Finalizing-Test
Disposed Finalizing-Test

是什么让你认为计时器是GCd?每次触发回拨时,我都会将当前时间写入控制台。2-3分钟后,它将在当前时间停止向控制台写入。这让我觉得这是gcd,这不是GC的工作方式,它不会随机清除变量。一定是发生了什么事情阻止了你的代码运行。除了在我上面发布的代码中添加两个数字之外,我没有任何其他逻辑,我也没有看到从代码中抛出任何其他异常。不过,这段代码将永远运行。有一个问题,你只需要在finally块中输入time start,否则你会多次调用它。每次我看到
while(true)
我的强迫症发作并想要改变it@TheGeneral别担心,它被编译成一个简单的草书循环,没有测试条件,这是最简单的方法。如果你不喜欢它,那么就不要进入固件开发lol。同样,这是基于问题中提供的示例。这比使用计时器更高效,资源消耗更少,而且管理起来也更容易。有一点不同,就是您的解决方案将无限期运行,而OPs将在按下enter键时终止。我不清楚这种差异对OP是否重要。@AdamG我会告诉你的。我将用适当的循环更新它并读取。
Testing Disposable-Test
Disposed Disposable-Test

Testing Finalizing-Test
Finalized Finalizing-Test
Disposed Finalizing-Test