【问题标题】:How to start an object containing a timer in a new thread?如何在新线程中启动包含计时器的对象?
【发布时间】:2012-06-22 16:49:22
【问题描述】:

如何在新线程中开始运行包含计时器的对象?

我有以下代码,我可能应该更改它:

    class MemoryCleaner : IDisposable
    {
        private readonly static MemoryCleaner Instance = new MemoryCleaner();

        private readonly Timer _memoryWatcher = new Timer(15 * 1000);

        public Timer MemoryWatcher
        {
            get
            {
                return this._memoryWatcher;
            }
        }

        public void Dispose()
        {
            _memoryWatcher.Elapsed -= memoryWatcher_Elapsed;
            this._memoryWatcher.Stop();
        }

        private void memoryWatcher_Elapsed(object sender, ElapsedEventArgs e)
        {
            var currentProcess = Process.GetCurrentProcess();
            var megaBytes = currentProcess.PrivateMemorySize64 / (1024 * 1024);
            if (megaBytes > 100)
            {
                // force an immediate garbage collection to free some unused memory quickly; this is an expensive process!
                GC.Collect();
            }
        }

        internal static void Start()
        {
            // this should be created in a new thread
            Instance.MemoryWatcher.Elapsed += Instance.memoryWatcher_Elapsed;
            Instance.MemoryWatcher.Start();
            GC.KeepAlive(Instance);
        }

        internal static void Stop()
        {
Instance.Dispose();
        }
    }

我想像这样使用它:

MemoryCleaner.Start();
// my memory thirsty code which generates so much garbage, e.g. downloads a document then disposes it.
MemoryCleaner.Stop();

我应该创建一个新线程,然后在该线程上创建 MemoryCleaner 对象的新实例并启动该对象。

这怎么可能?

一些背景信息: 基本上,代码应该做的是它应该每 15 秒检查一次主进程使用的内存,如果内存使用量超过 100MB,就会强制进行垃圾收集,因为会产生很多垃圾。

希望问题很清楚。

谢谢,

【问题讨论】:

  • 如果您的应用真正使用 >100MB,则强制每 15 秒进行一次 GC 只会让事情变得更糟,因为 保持 100MB 分页,这与你想要(允许操作系统在不使用时将其分页,从而释放物理 RAM)。
  • 您不会“运行”或“启动”对象。
  • 收集超过 100MB 的垃圾,让 GC 保留 100MB 的分页?你什么意思?

标签: c# multithreading timer garbage-collection


【解决方案1】:

如果您要创建System.Threading.TimerSystem.Timers.Timer,则在哪个线程上创建它并不重要——除非您指定同步对象,否则计时器无论如何都会在线程池线程上触发。为什么要为创建部分创建一个线程?

(无论如何我都不确定所有这些都是一个好主意,但这是另一回事......您还应该考虑让单例实现实现IDisposable 是否真的很明智。)

【讨论】:

  • 谢谢乔恩。我希望它在单独的线程上运行的原因是 elapse 在我的代码中不起作用。我不知道为什么。我尝试了一个简单的应用程序,但无法重现该问题,并且运行正常。不知道是什么原因导致我的产品应用程序无法正常工作。
  • @TheLight:我会专注于诊断差异,而不是仅仅将一些东西放在不同的线程上。
  • 我的应用程序使用繁重的多线程,因此如果我可以在单独的线程上完全运行 MemoryCleaner(不会与任何其他代码共享),那么它应该可以解决问题。我认为原因是当计时器过去时,它会等到线程池至少有 1 个可用线程,所以它找不到它并等到一个再次可用。
  • @TheLight:启动计时器后,它将启动线程池线程。您可以为此启动一个单独的线程just(并在 GC 之间休眠),但这是另一回事。我仍然认为诊断为什么应该起作用的东西不起作用是值得的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多