C#等待和同步 - 我误解了什么吗?

时间:2012-11-21 09:12:13

标签: c# windows-store-apps

我已经从Android移植到Windows Phone 7的应用程序,并且能够使用同步调用来存档io等没有太多问题(我使用线程,因此这简化了事情)。

但是,现在我正在移植到Windows 8商店应用程序,而且xiAsync()方法在api中猖獗。

我应该盲目地使用异步apis并希望最好吗?

我有各种疑惑......例如:

假设用户点击“保存”按钮以保存数据模型。所有保存都是异步完成的。这意味着用户可以在保存时更改数据模型。如果在中途进行修改,这会不会弄乱数据并破坏他的文件?

这如何让开发人员更容易?

我已经阅读了各种异步文章(例如this),但我觉得我可能会遗漏某些内容......

感谢您的见解。

6 个答案:

答案 0 :(得分:1)

您应该了解为什么 时使用异步方法,不要盲目使用它们。当然,这几乎适用于任何编程技术,但在异步情况下尤为重要,因为如果您不知道发生了什么,将来很容易搞砸。

重要的是要了解您提到的异步问题与async / await和使用手动线程解决方案没有区别。如果您不使用async / await(或手动构建的线程) )你的用户界面可能会感到迟钝或受到恼人的锁定。如果您确实使用它,则必须通过禁用输入控件,缓存正在保存的数据或者您拥有的内容来弥补UI 不会锁定的事实。

分散在现代API中的异步方法通常不会改变您对异步或多线程代码的看法,只是将这些想法应用到实际代码是多么容易。

答案 1 :(得分:1)

你是对的,你必须保护你的数据,但这与使用单独的线程没有什么不同。异步模式允许您创建响应式应用程序,而无需明确使用线程,但它无法解决访问共享资源的问题。我喜欢来自其中一个频道9视频的引用:响应能力是责任。

答案 2 :(得分:1)

在UI中使用async的想法是所有您的代码都在一个线程(UI线程)上运行。当用户单击“保存”按钮时,处理程序将运行。此时,UI正忙于运行代码,因此UI不是交互式的。准备好要发送到服务器的数据的快照后,启动异步保存并从技术上讲,处理程序已完成。控件传回UI,再次响应。

此时,用户可以更新数据模型,但操作系统不会查看数据模型。它只是确保将单独的数据缓冲区(您在“保存”按钮处理程序中创建的快照)发送到服务器。当发生这种情况时,再次在UI线程上执行异步回调。根据您使用的版本,您可能需要使用BeginInvoke手动将该调用转移到UI线程。

这与浏览器中的JavaScript使用的模型完全相同。

它并不能完全解决所有同步问题。例如,除非您在上载过程中禁用“保存”按钮,否则用户可以在服务器已经收到第一次保存时再次单击“保存”。但这只是服务器担心的一个问题,它最好能够应对两次同时尝试的保存。

您可能遇到的一个问题是您之前的应用程序版本。如果您在整个地方使用线程,您是否正确使用了锁或线程安全的数据结构?您描述的问题肯定存在于自由线程应用程序中!

答案 3 :(得分:1)

  

我应该盲目地使用异步apis并希望最好吗?

在Windows Phone平台上,您拥有以使用async API,但我建议您不要“盲目地”使用它们。先了解它们;我的博客上有async intro可能有帮助。

  

假设用户点击“保存”按钮以保存数据模型。所有保存都是异步完成的。这意味着用户可以在保存时更改数据模型。如果在中途进行修改,这会不会弄乱数据并破坏他的文件?

是。一种常见做法是在请求未完成时复制数据和/或禁用控件,例如,此代码将在首次请求保存时复制数据,并在保存完成之前禁用保存按钮:

public async Task SaveAsync(MyData data) { ... }

// Logically, this is an asynchronous ICommand.Execute implementation.
public async void SaveCommand()
{
  saveInProgress = true;
  dirty = false;
  MyData data = CopyData();
  await SaveAsync(data);
  saveInProgress = false;
}

// Logically, this is an ICommand.CanExecute implementation.
public bool CanSave { get { return !saveInProgress && dirty; } }
private bool saveInProgress, dirty;

使用线程保存时,您遇到了完全相同的问题。

  

这如何让开发人员更容易?

async代码比使用线程的代码更易于维护。

答案 4 :(得分:1)

请记住,仅仅因为代码异步执行,并不意味着您必须允许用户在保存数据时继续更改数据。它确实可以提供更好的用户体验IMHO,因为您可以决定阻止用户进一步更改数据的方法。

如果您同步保存并且需要很长时间(例如30秒),则用户将面临冻结,无响应的屏幕30秒。许多用户将在此时假设应用程序已崩溃。但是,虽然这种情况发生在异步模型中,但您只需显示一条消息(和状态栏),告诉用户发生了什么。此外,您可以选择允许他们访问应用程序的其他功能。

答案 5 :(得分:0)

  

我应该盲目地使用异步apis并希望最好吗?

不,当然不是。异步的东西是非常好的,为用户带来灵活的用户体验,但正如你提到的那样,在异步执行程序的那一刻,会给你的程序功能资产的管理带来复杂性。

移动(而不仅仅是)的基本思想是向用户提供一些progress信息,和/或来自UI控件的disablehide(功能访问点) )在特定时刻使用它会以某种方式伤害用户。