简体   繁体   English

强制GC使用另一个线程上下文

[英]Force GC to use another thread-context

I'm working with OpenGL and there are unmanaged objects I need to dispose of manually. 我正在使用OpenGL,并且有一些非托管对象需要手动处理。 (Specifially textures and vertex-buffers). (特别是纹理和顶点缓冲区)。

The problem is, that the function that frees a vertexbuffer absolutely has to be called from the main-thread (the only thread that can create or destroy such objects). 问题在于, 必须从主线程(唯一可以创建或销毁此类对象的线程)中调用释放顶点缓冲区的函数。

I already implemented IDisposable and the destructors for my managed objects correctly. 我已经为我的托管对象正确实现了IDisposable和析构函数。 The garbage-collector also calls the functions correctly. 垃圾收集器还可以正确调用函数。 But all this is bound to fail, because the garbage-collector runs on a different thread and when the GC calls the freeing-functions (DeleteBuffers(...), DeleteTexture(...), etc.) it crashes. 但是所有这些注定会失败,因为垃圾收集器在不同的线程上运行,并且当GC调用释放函数(DeleteBuffers(...),DeleteTexture(...)等)时,它会崩溃。

So I came up with 2 ideas to solve this: 所以我想出了两个想法来解决这个问题:

  1. Add the objects that have to be freed to a list, then check that list in the main thread. 将必须释放的对象添加到列表中,然后在主线程中检查该列表。 Problem: Requires synchronisation / locking which I want to avoid. 问题:我需要避免同步/锁定。 Maybe use a BlockingCollection<> ? 也许使用BlockingCollection <>?

  2. Somehow force the GC to use the main-thread to do its job. 以某种方式迫使GC使用主线程来完成其工作。

Is there a way which I don't know to do this? 有我不知道的方法吗? How should I dispose those objects correctly? 我应该如何正确放置这些物体? Do I have to cleanup myself? 我需要自己清理吗? (meaning I stop using the destructor and always free the objects myself?) (这意味着我停止使用析构函数,并且总是自己释放对象吗?)

the idea is simple you have a Queue (Use ConcurentQueue for thread safety) have your finlizers fill this queue and your main loop empty it. 这个想法很简单,您有一个队列(使用ConcurentQueue保证线程安全),让您的整理器填充此队列,而主循环将其清空。

try this link: http://www.opentk.com/node/101 尝试以下链接: http : //www.opentk.com/node/101

A user of the Tao Framework implemented this idea with promising results. He wrote wrappers for OpenGL resources and implemented the disposable pattern like this:
private void Dispose(bool manual)
{
    if (!disposed)
    {
        if (manual)
        {
             Gl.glDeleteTextures(1, ref _tid);
             GC.SuppressFinalize(this);
             disposed = true;
        }
        else
        {
            GC.KeepAlive(SimpleOpenGlControl.DisposingQueue);
            SimpleOpenGlControl.DisposingQueue.Enqueue(this);
        }
    }
}

SimpleOpenGlControl.DisposingQueue is a queue that holds references to OpenGL resources. SimpleOpenGlControl.DisposedQueue是一个队列,其中包含对OpenGL资源的引用。 It is visited regularly during program execution, disposing data contained therein. 在程序执行期间定期对其进行访问,以处理其中包含的数据。 Note that the 'else' clause will never be executed, unless you actually forget to release resources. 注意,除非您实际上忘记释放资源,否则将永远不会执行“ else”子句。 This is the best of both worlds: you can release resources manually (with no performance hit), but the garbage collector will still clean up after you if you forget something. 这是两全其美的方法:您可以手动释放资源(不会影响性能),但是如果您忘记了某些内容,垃圾收集器仍会在您清理之后。 Even better, the implementation is dead simple! 更好的是,实现非常简单! Now, we only need to find out how to handle multiple OpenGL contexts. 现在,我们只需要了解如何处理多个OpenGL上下文。

Have you tried: 你有没有尝试过:

GCSettings.LatencyMode = GCLatencyMode.Batch;

This should stop GC running on other threads. 这应该停止GC在其他线程上运行。

MSDN MSDN

Disables garbage collection concurrency and reclaims objects in a batch call. 禁用垃圾回收并发并在批处理调用中回收对象。 This is the most intrusive mode. 这是最侵入的模式。 This mode is designed for maximum throughput at the expense of responsiveness. 此模式旨在最大程度地提高吞吐量,但会降低响应速度。

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

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