委托Closure没有内存分配

时间:2017-04-23 00:50:29

标签: c# multithreading unity3d delegates closures

我写了一个Thread helper类,可以用来在Unity的主线程中执行一段代码。

这是蓝色打印功能:

public static void executeInUpdate(System.Action action)

完整的脚本非常长,会使这篇文章变得不必要。您可以看到脚本帮助程序类here的其余部分。

然后,我可以使用另一个Thread的统一API,如下所示:

UnityThread.executeInUpdate(() =>
{
    transform.Rotate(new Vector3(0f, 90f, 0f));
});

问题在于,当我使用在该委托之外声明的变量时,它会分配内存。上面的代码每帧分配 104 字节。这是因为在该闭包内部使用的transform变量。

现在看起来似乎没什么,但我这样做每秒60次,我有大约6个相机,我需要连接到屏幕上并显示图像。我不喜欢产生的垃圾量。

以下是我如何从相机下载图像并将其上传到Unity的示例。我每秒约60帧。 receiveVideoFrame()函数在单独的Thread上运行。它下载图像,将其发送到Unity的主Thread,Unity将图像字节上传到Texture2D。然后,Texture2D会显示RawImage。由于UnityThread.executeInUpdate而捕获闭包时会发生分配。

bool doneUploading = false;
byte[] videoBytes = new byte[25000];
public Texture2D videoDisplay;

void receiveVideoFrame()
{
    while (true)
    {
        //Download Video Frame 
        downloadVideoFrameFromNetwork(videoBytes);

        //Display Video Frame 
        UnityThread.executeInUpdate(() =>
        {
            //Upload the videobytes to Texture to display
            videoDisplay.LoadImage(videoBytes);
            doneUploading = true;
        });

        //Wait until video is done uploading to Texture/Displayed
        while (!doneUploading)
        {
            Thread.Sleep(1);
        }

        //Done uploading Texture. Now set to false for the next run
        doneUploading = false;

        //Repeat again
    }
}

如何在不导致内存分配的情况下使用闭包?

如果不可能,还有其他办法吗?

我可以删除我用来在主线程中执行代码的类,并在主脚本中重写这些逻辑,但这会很麻烦而且很长。

1 个答案:

答案 0 :(得分:1)

经过几个小时的实验,我发现如果你把带闭包的代码放在一个函数中,然后将它缓存到Action中的Start变量一次或{ {1}}函数,当你在while循环中调用它时,闭包内存分配将会消失。

此外,我将Awake布尔变量设为doneUploading,以便volatile都可以看到更改。我不认为此Threads变量需要lock关键字。

boolean

如果有人发现任何不好的事,我愿意接受更多改进。虽然,我已经解决了我的问题。闭包再分配内存。