我可以告诉.NET GC不要使用某些线程吗?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (45)

我正在研究从C ++到C#重写相对较小的服务的可能性。该服务有两个主要功能:

  1. 偶尔执行一次HTTP请求。它们涉及几个高级任务,如JSON编码/解码,base64编码/解码和HTTP请求本身,对此C ++并不是很棒;
  2. 执行许多实时的音频相关任务,这些任务有严格的截止日期,对此C#不是很棒。

实时任务由独立的库进行处理,该库独立执行线程工作,几乎不与服务的其他部分进行交互。服务的其余部分每隔5分钟就会从HTTP请求中获取一小部分数据。

事情是,由于实时部分有严格的最后期限,我不能真正容忍库的线程上的GC暂停。在我自己的代码方面,应该有足够的时间让GC在Web请求之间运行,但是我无法忍受在我尝试向数据库中提供数据时它启动了。

发现我可以创建一个垃圾收集器不会开始使用的关键部分GC.TryStartNoGCRegion(),它解决了一半的问题。

但是,我仍然不知道是否有办法告诉.NET GC独立保留不运行托管代码的特定线程。那可能吗?

提问于
用户回答回答于

没有检查它,但是,我会继承线程或任务,无论你使用什么:

public class SuppressedThread : Thread
{            
    protected override void Finalize()
    {
         try
         {
          // kill what you want
         }
         finally
         {
          base.SupressFinalizeFinalize();
         }
    }
}

public class SuppressedThread : Thread, IDisposable
{    
    protected override void Dispose()
    {
         try
         {
          // kill what you want
         }
         finally
         {
          GC.SupressFinalize();
         }
    }
}

那么你可以正常使用它

var newThread = new SuppressedThread(DoWork);
newThread.Start(42);

你怎么看?

用户回答回答于

正如已经指出的那样,当应用程序配置为在Workstation GC模式下运行时,垃圾收集器不会挂起执行本机代码的线程。在这种情况下,如果服务收到请求,我会尝试这样的事情......

    private bool _running = true;
    private int _workCounter = 0;
    private AutoResetEvent _workFlag = new AutoResetEvent(false);
    private void RunNoGCNativeCode(params object[] args)
    {
        // Increase the work counter to determine how many requests are being processed
        if (Interlocked.Increment(ref _workCounter) == 1)
        {
            // Try to start a No GC Region
            GC.TryStartNoGCRegion(1 * 1024 * 1024 * 1024, true);
        }
        // TODO: Prep data and execute your native code
        // TODO: Process response
        // TODO: Dispose of anything that is no longer in use and null objects as needed
        if (Interlocked.Decrement(ref _workCounter) == 0 && GCSettings.LatencyMode == GCLatencyMode.NoGCRegion)
        {
            GC.EndNoGCRegion();
        }
        // Notify Manual Collection thread work has been completed
        _workFlag.Set();
    }

在另一个线程上...

    private void WaitForNoWorkThenGC()
    {
        // Continue running thread while in use
        while (_running)
        {
            // Wait for some work to be complete
            _workFlag.WaitOne();
            // If there is no work being processed call GC.Collect() 
            if (_workCounter == 0)
            {
                GC.Collect();
            }
        }
    } 

这应该有助于控制GC何时发生,以最大限度地减少对应用程序的影

扫码关注云+社区