gpt4 book ai didi

c# - 有没有办法防止ThreadPool产生垃圾?

转载 作者:行者123 更新时间:2023-12-03 03:14:53 25 4
gpt4 key购买 nike

执行多线程方法会产生垃圾。这是为什么?我们可以阻止它吗?

ThreadPool.QueueUserWorkItem(callBack, state);

enter image description here

编辑:我所说的垃圾是指创建后超出范围的对象。由于它是旧版本的 mono,垃圾收集非常慢。因此,您从 GC 中节省的每一 kb 都是一次胜利。如果您不熟悉 Unity 引擎,请在屏幕截图中查看突出显示行上的 GC 列。它说0.6kb。因此它会产生 600 字节的垃圾。回调代码不会创建任何垃圾,因此它源于 ThreadPool.QueueUserWorkItem

编辑2:这里有一个更具体的例子来进一步阐述:

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

public void DummyMethod(object meaningless)
{
}
}

这是结果。请查看突出显示的行。 GC 列显示 285Bytes。由于DummyMethod没有做任何事情,所以垃圾与ThreadPool有关。

enter image description here

编辑3:为了缓解这种情况并找到替代方案,可以使用一个工作线程来执行队列中的作业。

没问题,但如果有多个可用的 CPU,它必须在 Unity 使用的 CPU 以外的 CPU 上运行。 Unity 几乎可以在单个线程中完成所有操作,因此同一 CPU 上的后台工作程序将是一场灾难。此外,它是一个跨平台项目,因此仅适用于 Windows 的解决方案将无法工作。所以基本上我需要一个工作线程解决方案,并知道是否可以实现一个线程的 CPU 是否与另一个线程的相同。

最佳答案

当您ThreadPool.QueueUserWorkItem(DummyMethod);时,它实际上隐式地将您的代码转换为ThreadPool.QueueUserWorkItem(new WaitCallback(DummyMethod));,该回调可能是要放入 GC 的项目。尝试使用以下代码显式创建委托(delegate)并保留对其的引用,看看它是否会减少 GCable 数据量。

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)
{
}
}

更新:这是单线程后台工作程序的极其基本的实现,为您提供一个起点。下面的代码未经测试,可能会表现得很糟糕,但它确实为您提供了一个想法作为起点。

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
}
}
}
}

关于c# - 有没有办法防止ThreadPool产生垃圾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34813146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com