【问题标题】:IO operations with Task.RunTask.Run 的 IO 操作
【发布时间】:2013-07-22 18:47:31
【问题描述】:

我用的是MonoGame,不过这个跟winrt async和IO关系比较大,所以请不要重定向到gamedev。

我想异步加载游戏内容,以便更新加载屏幕的进度。我将每个 ContentManager.Load 调用放在一个 Task 中,然后放在我的 BeginLoading 方法中,我只是遍历所有任务并一次性启动它们。

到目前为止,这似乎在我的测试中有效,但我的问题是这是否可以扩展。

如果我为异步添加 100 个资产,这将产生 100 个任务,这些任务将同时从磁盘 al 中读取。 WinRT 可以这样扩展吗?

实际上,我是否应该将任务数量限制为核心/物理胎面的数量?还是我应该只有一个活动任务?

【问题讨论】:

  • 为什么不只有一个任务来加载所有内容?
  • 我根据已完成任务的数量更新加载进度(加载百分比)。每个 Content.Load 调用创建一个任务也更容易。除非有人有更好的建议。

标签: .net io .net-4.5 monogame winrt-async


【解决方案1】:

创建 100 个任务不一定会启动 100 个同时执行的并发线程。您受限于可用的池线程数,以及 TPL 的东西是并发运行的合理数量的任务。在 4 核机器上,您可能不会获得超过三四个并发任务。

也就是说,您最好启动一个任务,然后遍历您的资产列表并一次加载一个。由于多个线程向同一个驱动器发出 I/O 请求,这些线程很可能会花费大量时间在磁盘上等待,并且不会在并发处理方面做太多事情。让许多线程进行加载几乎没有任何好处,因为它们大部分时间都处于空闲状态。如果您发现您的多个加载程序线程比您启动一个一次加载所有资产的单个线程需要更长的时间来完成,我不会感到惊讶。

我不明白创建 100 个单独的任务,每个任务加载一个资产,比按顺序加载这 100 个资产的单个任务更容易编写代码。我想不出你怎么能创建这样的数据结构。

简而言之,您不必将任务数限制为可用内核数; TPL 将为您做到这一点。但是你最好只做一个任务。充其量,使用多个并发线程略微会更好,但这不太可能。

【讨论】:

  • TPL 根据可用内核数量管理线程数量这一事实解决了我的大部分担忧。剩下的问题是如何从单个线程更新估计的进度?这似乎比简单地查看剩余线程数和已完成线程数更复杂。
  • @RecursiveCall,如果你知道你要加载多少资源并且你知道你加载了多少,那有什么问题?
  • 啊,现在的问题更具体到 MonoGame/XNA 加载资产的方式(我需要将字符串和 T 传递给 Load 方法)。我想这更像是一个通用的 C# 问题。
猜你喜欢
  • 1970-01-01
  • 2018-07-03
  • 1970-01-01
  • 2014-02-05
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2013-04-25
  • 1970-01-01
相关资源
最近更新 更多