异步写入文件,但按顺序

时间:2015-04-30 08:36:34

标签: c# asynchronous

我有一些代码可以将数据从对象保存到XML。这使得用户界面锁定了几秒钟,所以我做了它就不会这样了。

foreach (Path path in m_canvasCompact.Children)
{
   Task.Run(() => WritePathDataToXML(false, path));
}

Private void WritePAthDataToXML(bool is32x32, Path path)
{

   //stuff going on... 

   xmlDoc.Root.Descendants.......Add(iconToAdd);
   xmlDoc.Save(..);
}

问题是(正如预期的那样)数据写入XML的顺序是随机顺序,具体取决于任务完成的速度(我假设)

我可能会写一些代码看到XML的代码,并在完成所有内容后重新排列它,但这并不理想。无论如何在一个单独的线程上执行此操作,但可能一次只执行一次,因此它们会以正确的顺序执行并保存。

感谢。

2 个答案:

答案 0 :(得分:6)

听起来你想要一个生产者/消费者队列。您可以使用BlockingCollection<T>轻松地进行操作。

  1. 创建阻止集合
  2. 启动一个任务,该任务将从集合中读取,直到它完成&#34; (最简单的GetConsumingEnumerable),写入文件
  3. 将所有相关项添加到集合中 - 确保您执行触及UI线程中UI元素的所有
  4. 告诉收藏品&#34;完成&#34; (CompleteAdding
  5. 或者,正如评论中所建议的那样:

    • 在UI线程中,使用UI元素创建一个包含所需信息的集合 - 基本上您不想触摸非UI线程中的UI元素。
    • 启动任务以将该集合写入磁盘;可选择等待该任务(不会阻止用户界面)

    这更简单,但它确实意味着在开始写作之前在内存中构建整个集合。使用第一种方法,您可以在编写时添加到集合中 - 尽管完全有可能如果构建集合比写入磁盘快得多,那么无论如何,您最终都会在内存中找到整个内容。 。如果这是不可行的,你需要一些方法来轻轻地添加&#34;轻轻地&#34;从UI线程,不阻止它。如果BlockingCollection使用AddAsync方法会很好,但我看不到。

    我们对您使用Path元素所做的事情了解不足,无法为您提供示例代码,但希望这足以成为一个起点。

答案 1 :(得分:0)

Task

中运行整个循环
Task.Run(()=>{
    foreach (Path path in m_canvasCompact.Children)
    {
       WritePathDataToXML(false, path);
    }
});

这仍然会花费相同的时间,但不应该阻止用户界面。