有没有一种方法,以防止垃圾制作的线程池? [英] Is there a way to prevent the ThreadPool from making garbage?

查看:142
本文介绍了有没有一种方法,以防止垃圾制作的线程池?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

执行多线程的方法使得垃圾。 ?这是为什么,我们可以阻止它。

Executing multithreaded methods make garbage. Why is that and can we prevent it?

ThreadPool.QueueUserWorkItem(callBack, state);

编辑:
垃圾我的意思是被创建,然后走出了范围的对象。垃圾收集是因为它的老版单的速度很慢。所以每KB保存从GC是一个双赢。如果你不熟悉的Unity引擎,在截图中,请参阅突出显示的行中的气相色谱柱。它说0.6kb。因此,创建600个字节的垃圾。所以这是从ThreadPool.QueueUserWorkItem根的回调代码不产生任何垃圾

By garbage I mean objects that are created and then went out of scope. The garbage collection is very slow because of it's old version of mono. So every kb you save from the GC is a win. If you are not familiar with the unity engine, In the screenshot please see The GC column on the highlighted row. It says 0.6kb. Therefore it create 600 bytes of garbage. The callback code is not creating any garbage so this is rooted from ThreadPool.QueueUserWorkItem

编辑2::要进一步详细说明这里是一个更具体的例子

EDIT 2: To elaborate further here is a more concrete example:

public class TestThread : MonoBehaviour
{
    public void Update()
    {
        if (Time.frameCount%10 == 0)
            ThreadPool.QueueUserWorkItem(DummyMethod);
    }

    public void DummyMethod(object meaningless)
    {
    }
}

下面是结果。请看突出显示的行。 GC色谱柱说285Bytes。由于DummyMethod没有做任何事情,垃圾关系到线程池。

Here is the result. Please look at the highlighted row. The GC column says 285Bytes. Since DummyMethod is not doing anything, the garbage is related to ThreadPool.

修改3:
放松情况,并找到一个替代,这将是可以接受的一个工作线程从队列中执行作业。

Edit 3: To relax the situation and find an alternative, it would be acceptable to have a worker thread that executes jobs from a queue.

这将是确定但它的必须在其他一个比统一使用是否有可用多个CPU的CPU上运行。团结确实在单个线程几乎任何所以相同的CPU的后台工作将是一场灾难。此外,它是一个跨平台的项目,所以只有Windows的解决方案将无法工作。所以基本上我需要一个工作线程解决方案,并知道是否可以实现,如果一个线程的CPU是一样的另一个线程的。

It would be OK But it MUST run on CPU other than the one unity uses if there are multiple CPUs available. Unity does nearly anything in a single thread so a background worker on the same CPU would be a disaster. Also it is a cross platform project so windows-only solutions won't work. So basically I need a worker thread solution and to know if it possible to realize if a thread's CPU is the same as another thread's.

推荐答案

ThreadPool.QueueUserWorkItem(DummyMethod); 它实际上是隐式转向你的代码中 ThreadPool.QueueUserWorkItem(新WaitCallback(DummyMethod)); ,该回调可能,这是获得投入到GC的项目。试试下面的代码来显式创建委托,并保持对它的引用,看看它是否降低GCable的数据量。

When you ThreadPool.QueueUserWorkItem(DummyMethod); it actually is implicitly turning your code in to ThreadPool.QueueUserWorkItem(new WaitCallback(DummyMethod));, that callback may be the item that is getting put on to the GC. Try the following code to explicitly create the delegate and keep a reference to it and see if it reduces the amount of GCable data.

public class TestThread : MonoBehaviour
{
    private readonly WaitCallback _callback;

    public TestThread()
    {
        _callback = new WaitCallback(DummyMethod);
    }

    public void Update()
    {
        if (Time.frameCount%10 == 0)
            ThreadPool.QueueUserWorkItem(_callback);
    }

    public void DummyMethod(object meaningless)
    {
    }
}

更新:这是一个非常基本的实现单线程后台工作的,给你一个起点。下面的代码是未经测试,可能可怕的表演,但它确实给你一个想法为出发点。

UPDATE: Here is a extremely basic implementation of a single threaded background worker, to give you a starting point. The below code is untested and may perform horribly, but it does give you an idea as a starting point.

public class BasicBackgroundWorker
{
    private readonly Thread _backgroundWorkThread;
    private readonly Queue<Action> _queue = new Queue<Action>();
    private readonly ManualResetEvent _workAvailable = new ManualResetEvent(false);

    public BasicBackgroundWorker()
    {
        _backgroundWorkThread = new Thread(BackgroundThread)
        {
            IsBackground = true,
            Priority = ThreadPriority.BelowNormal,
            Name = "BasicBackgroundWorker Thread"
        };
        _backgroundWorkThread.Start();
    }

    public void EnqueueWork(Action work)
    {
        lock (_queue)
        {
            _queue.Enqueue(work);
            _workAvailable.Set();
        }
    }

    private void BackgroundThread()
    {
        while (true)
        {
            _workAvailable.WaitOne();
            Action workItem;
            lock (_queue)
            {
                workItem = _queue.Dequeue();
                if (_queue.Count == 0)
                {
                    _workAvailable.Reset();
                }
            }
            try
            {
                workItem();
            }
            catch (Exception ex)
            {
                //Log exception that happened in backgroundWork
            }
        }
    }
}

这篇关于有没有一种方法,以防止垃圾制作的线程池?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆