我想异步读取图像文件,我正在尝试使用 C# 中的 async/await
来实现。但是,我仍然注意到此实现存在明显滞后。使用探查器,我非常有信心是 FileStream.ReadAsync()
方法需要很长时间才能完成,而不是异步执行并停止游戏更新。
我注意到这种方式比仅使用 File.ReadAllBytes
更延迟,这很奇怪。我不能使用仍然会导致一些滞后的方法,我不想停止帧速率。
这是一些代码。
// Static class for reading the image.
class AsyncImageReader
{
public static async Task<byte[]> ReadImageAsync(string filePath)
{
byte[] imageBytes;
didFinishReading = false;
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
{
imageBytes = new byte[fileStream.Length];
await fileStream.ReadAsync(imageBytes, 0, (int) fileStream.Length);
}
didFinishReading = true;
return imageBytes;
}
}
// Calling function that is called by the OnCapturedPhotoToDisk event. When this is called the game stops updating completely rather than
public void AddImage(string filePath)
{
Task<byte[]> readImageTask = AsyncImageReader.ReadImageAsync(filePath);
byte [] imageBytes = await readImageTask;
// other things that use the bytes....
}
最佳答案
您不需要任务来异步加载图像。您可以使用 Unity 的 UnityWebRequest
和 DownloadHandlerTexture
API 加载。 UnityWebRequestTexture.GetTexture
简化了这一点,因为它会自动为您设置 DownloadHandlerTexture
。这是在引擎盖下的另一个线程中完成的,但您使用协程来控制它。
public RawImage image;
void Start()
{
StartCoroutine(LoadTexture());
}
IEnumerator LoadTexture()
{
string filePath = "";//.....
UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(filePath);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError || uwr.isHttpError)
{
Debug.Log(uwr.error);
}
else
{
Texture texture = ((DownloadHandlerTexture)uwr.downloadHandler).texture;
image.texture = texture;
}
}
您还可以使用 Thread
API 在另一个线程中加载文件。更好的是,使用 ThreadPool
API。他们中的任何一个都应该工作。加载图像字节数组后,要将字节数组加载到 Texture2D
中,您必须在主线程中执行此操作,因为您不能在主线程中使用 Unity 的 API。
要在加载完图像字节后从另一个线程使用 Unity 的 API,您需要一个包装器来执行此操作。下面的示例是使用 C# ThreadPool
和我的 UnityThread
API 完成的,这简化了从另一个线程使用 Unity 的 API。你可以抢UnityThread
从这里开始。
public RawImage image;
void Awake()
{
//Enable Callback on the main Thread
UnityThread.initUnityThread();
}
void ReadImageAsync()
{
string filePath = "";//.....
//Use ThreadPool to avoid freezing
ThreadPool.QueueUserWorkItem(delegate
{
bool success = false;
byte[] imageBytes;
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true);
try
{
int length = (int)fileStream.Length;
imageBytes = new byte[length];
int count;
int sum = 0;
// read until Read method returns 0
while ((count = fileStream.Read(imageBytes, sum, length - sum)) > 0)
sum += count;
success = true;
}
finally
{
fileStream.Close();
}
//Create Texture2D from the imageBytes in the main Thread if file was read successfully
if (success)
{
UnityThread.executeInUpdate(() =>
{
Texture2D tex = new Texture2D(2, 2);
tex.LoadImage(imageBytes);
});
}
});
}
关于c# - 异步读取图像文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52357990/