【问题标题】:Making sync code depend on async code使同步代码依赖于异步代码
【发布时间】:2014-11-04 09:37:18
【问题描述】:

在我当前的项目中,我将某些对象的状态存储在 XML 文件中。当我在 WPF 项目中工作时,我需要使用异步方法来执行此操作。

因此,我在加载我的应用程序时遇到了问题。我要从 XML 文件中重新创建这些对象的状态,这必须异步完成,但我的内容取决于这些对象的状态,在我的情况下,这导致对象在我之前没有完全实例化与他们合作。

简而言之:我的同步方法取决于我的异步方法在启动我的应用程序时实例化了我的对象。

下面是一段代码,展示了我如何读取整个文件夹的 xml 文件并生成对象列表。

public List<Restaurant> restaurant = new List<Restaurant>();

public async void ReadRestaurantAsync()
{
    IStorageFolder filesFolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("folder");
    var storageFiles = await filesFolder.GetFilesAsync();

    foreach (var storageFile in storageFiles)
    {
        using (IRandomAccessStream stream = await storageFile.OpenAsync(FileAccessMode.Read))
        using (Stream inputStream = stream.AsStreamForRead())
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof (Restaurant));
            Restaurant objectRead = serializer.ReadObject(inputStream) as Restaurant;
            restaurant.Add(objectRead);
        }
    }
} 

现在,当我从 MainPage 调用此异步方法时,我无法使用对象 Restaurant,因为它尚未完全实例化。

我想在尝试与 Restaurant 交互之前,我必须等待方法完全执行,但这似乎也有点奇怪,因为它破坏了关于异步方法的整个想法。

【问题讨论】:

    标签: c# xml wpf asynchronous


    【解决方案1】:

    好吧,你想await 异步代码,而不是直接等待。这将使您的 GUI 在加载数据时保持响应(并且可能会显示加载消息,具体取决于加载所需的时间)。

    同步方法调用异步方法和等待没有意义。如果您这样做,您可以首先使用同步方法并节省开销。您希望一直保持异步(是的,这确实意味着您不想在构造函数中加载数据 - 但无论如何您都不应该这样做)。

    请注意,您可以在 WinForms / WPF 事件处理程序中使用 await 就可以了,因此请继续处理这些 LoadDataBinding 事件等。

    简而言之:当您发现自己的同步代码在等待异步代码时 - 您的设计可能存在缺陷。无论如何,它表明您忽略了同步问题等,当您开始使用 await 时,这些问题并不会神奇地消失 - 访问全局变量仍然是一个非常糟糕的主意。相反,您希望任务返回一个值(在您的情况下,一个可枚举的 Restaurant)并将这些值添加到 UI 线程中的全局列表中(即,在被回发到同步上下文的延续上)。现在,您正在实际执行此操作,因为您正在处理 UI 线程上的所有异步回调,但这可能是不必要的,实际上可能是一个愚蠢的开销,使加载需要更长的时间。

    认为异步。不要在旅途中停下来。

    【讨论】:

    • 谢谢!很好的解释。
    猜你喜欢
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多