制作同步代码取决于异步代码

时间:2014-11-04 09:37:18

标签: c# xml wpf asynchronous

在我当前的项目中,我将某些对象的状态存储在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进行交互之前必须等待完全执行的方法,但这似乎有点奇怪,因为它破坏了关于异步方法的整个想法。

1 个答案:

答案 0 :(得分:2)

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

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

请注意,您可以在WinForms / WPF事件处理程序中await正常运行,因此请继续查看LoadDataBinding个事件等。

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

思考异步。不要在旅途中停下来。