【发布时间】:2018-10-29 21:38:30
【问题描述】:
我正在尝试在更新进度条时逐行读取文件(两个 GUI 纹理,其中一个宽度 (maxWidth * currentPercentage) 具有浮动扩展)。
我有两个实现:
public static string ThreadedFileRead(string path, Action<float> percAction)
{
FileInfo fileInfo = new FileInfo(path);
StringBuilder sb = new StringBuilder();
float length = fileInfo.Length;
int currentLength = 0;
using (StreamReader sr = new StreamReader(path))
{
while (!sr.EndOfStream)
{
string str = sr.ReadLine();
sb.AppendLine(str);
// yield return str;
percAction(currentLength / length);
currentLength += str.Length;
Interlocked.Add(ref currentLength, str.Length);
}
percAction(1f);
return sb.ToString();
}
}
使用以下实现:
// Inside a MonoBehaviour
public void Start()
{
string fileContents = "";
StartCoroutine(LoadFileAsync(Application.dataPath + "/Data/file.txt", (s) => fileContents = s));
}
public IEnumerator LoadFileAsync(string path, Action<string> fin)
{
string contents = "";
lock (contents)
{
var task = Task.Factory.StartNew(() =>
{
contents = F.ThreadedFileRead(path, (f) => currentLoadProgress = f);
});
while (!task.IsCompleted)
yield return new WaitForEndOfFrame();
fin?.Invoke(contents);
}
}
但这会阻止当前的 GUI(我不知道为什么)。
我也用过这个:
// Thanks to: https://stackoverflow.com/questions/41296957/wait-while-file-load-in-unity
// Thanks to: https://stackoverflow.com/a/34378847/3286975
[MustBeReviewed]
public static IEnumerator LoadFileAsync(string pathOrUrl, Action<float> updatePerc, Action<string> finishedReading)
{
FileInfo fileInfo = new FileInfo(pathOrUrl);
float length = fileInfo.Length;
// Application.isEditor && ??? // Must review
if (Path.IsPathRooted(pathOrUrl))
pathOrUrl = "file:///" + pathOrUrl;
/*
using (var www = new UnityWebRequest(pathOrUrl))
{
www.downloadHandler = new DownloadHandlerBuffer();
CityBenchmarkData.StartBenchmark(CityBenchmark.SendWebRequest);
yield return www.SendWebRequest();
CityBenchmarkData.StopBenchmark(CityBenchmark.SendWebRequest);
while (!www.isDone)
{
// www.downloadProgress
updatePerc?.Invoke(www.downloadedBytes / length); // currentLength / length
yield return new WaitForEndOfFrame();
}
finishedReading?.Invoke(www.downloadHandler.text);
}
*/
using (var www = new WWW(pathOrUrl))
{
while (!www.isDone)
{
// www.downloadProgress
updatePerc?.Invoke(www.bytesDownloaded / length); // currentLength / length
yield return new WaitForEndOfFrame();
}
finishedReading?.Invoke(www.text);
}
}
使用以下实现:
public IEnumerator LoadFileAsync(string path, Action<string> fin)
{
yield return F.LoadFileAsync(path, (f) => currentLoadProgress = f, fin);
}
我分享的最后一段代码有两部分:
- 被注释的部分也阻塞了主线程。
- 我使用的 WWW 类(将来会弃用)不会阻塞主线程,但它只会在进度条上显示两个步骤(如 25% 和 70%)。
我不知道为什么会发生这种情况,以及是否有更好的方法。
因此,欢迎对此提供任何帮助(指导)。
【问题讨论】:
-
“过时的部分(WWW 类)不会阻塞主线程” 抱歉,您的问题中没有 WWW 代码。您使用了 UnityWebRequest,它们是不同的。另外,你能告诉我你是怎么打电话给
ThreadedFileRead的吗?也显示函数名和返回类型。 -
是的,我正在使用
using (var www = new WWW(pathOrUrl))。要查看我在哪里调用ThreadedFileRead,请查看第二个代码块(我编辑了我的问题)。
标签: c# unity3d stream coroutine