c# - 使用 async/await 的技巧

标签 c# unity-game-engine async-await uwp hololens

过去几天我一直在阅读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/

相关文章:

macos - 如何修复: 'unitypurchasing' is already in use by another application?

javascript - 为什么我的无限循环在异步函数中时会阻塞?

c# - 在静态方法中使用异步函数

javascript - 导出异步等待变量并在 JS 中完成 "awaiting"后将其导入另一个文件

javascript - 从数据库中存储的字符串创建 html5 页面

c# - 如何复制具有取消复制功能的文件?

ios - Unity 窗口 + 原生 iOS 窗口在同一个 App 上?

c# - 防止用户关闭通过 C# 程序打开的应用程序

c# - "A cycle was detected in the set of changes"尝试向数据库添加循环链表时

c# - 如何向 EditorGUILayout.TextArea 添加自动换行?