过去几天我一直在阅读C# 异步编程。原因是 UWP 中的文件选择器(这是必要的,因为我正在 Unity 中为 Hololens 2 编程)。尽管有很多来源,即 1 , 2 , 3 ,我对正确使用有一些理解问题,也许这里有经验的用户可以给我一些提示。
我正在尝试做的事情的一个例子:
程序开始:
public class SceneUIHandler : MonoBehaviour
{
openFile()
{
pickFile(); // calls await filepicker.PickSingleFileAsync();
loadData(path); // calls FileLoader.loadFile with path from filepicker for the reader
showData(); // should display the data
}
}
加载器:
public class FileLoader:
{
async void loadFile(string path)
{
Task<StreamReader> streamReaderTask = getStreamReader(filePath);
StreamReader sr = await streamReaderTask;
// after that read file with the StreamReader...
...
}
async Task<StreamReader> getStreamReader(string path)
{
StorageFile file = await StorageFile.GetFileFromPathAsync(path);
var randomAccessStream = await file.OpenReadAsync();
Stream stream = randomAccessStream.AsStreamForRead();
StreamReader str = new StreamReader(stream);
return str;
}
}
因此,我使用文件选择器获取路径,然后在 FileLoader 类中使用该路径调用文件并创建流读取器。到目前为止一切正常。
我的问题是,如果创建读取器需要更长的时间,代码会因等待而停止,并在方法 loadData()
之后在 SceneUIHandler 的 openFile()
中再次相应跳转>。但之后是 showData()
,这里我希望数据已经加载。根据教程,我现在将使用 openFile()
async 在这里编写 await loadData()
。
如果我这样做,我必须一个接一个地异步一个方法,因为我必须在某个地方等待,直到加载数据,否则我无法显示、更改、与(未加载的)数据交互。但是通过async + wait我等待并继续前面的方法(也依赖于数据)。
我必须如何或在哪里停止,或者在使用异步时是否必须以不同的方式分离代码,以便代码流的其余部分独立于数据?
我现在还得到一个跨线程调用异常
,可能是通过创建和调用略有不同的 getStreamReader(string path) 方法,该方法仅返回 BinaryReader 而不是 StreamReader。
最佳答案
我还建议阅读我的 async best practices文章。前两个最佳实践仍然是最重要的。
From the tutorials I would now make openFile() async to write an await loadData() here.
第一个最佳实践是“避免async void
”,因为您的代码无法知道该方法何时完成。换句话说,使用async Task
而不是async void
,并等待
该方法调用。
If I do that I have to async one method after the other because I have to wait somewhere until the data is loaded otherwise i can't display, change, interact with the (not loaded) data. But by async + await I wait and continue in the previous method (which also relies on the data).
How or where do I have to stop, or do I have to separate the code differently when working with async so that the rest of the code flow is independent of the data?
第二个最佳实践是“始终使用async
”。一开始感觉奇怪很正常,但这是正确的程序。
最终,您将回归到您的框架。对于 UWP/Unity,您将拥有最高级别的 UI。您需要做的是显示某种“正在加载...”屏幕(立即且同步),然后在异步工作完成时更新。我有一篇关于async data binding的文章这是从 MVVM/WPF 角度编写的,但相同的想法适用于任何 UI 框架。
关于c# - 使用 async/await 的技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73218176/