添加到列表时尝试读取写保护的内存

时间:2016-10-14 09:08:50

标签: c# uwp

我有一个代码,它应该从文件夹中获取所有图片,将它们放入名为" PhotoInspection"的对象中,添加一些信息并将此对象放入列表中。请参阅以下代码

private async void btnSend_Click(object sender, RoutedEventArgs e)
{
    bool isOn = tsOnOff.IsOn;
    TextBlock tbChosen = new TextBlock();

    tbChosen = lbInspections.SelectedItem as TextBlock;

    string chosen = tbChosen.Text;

    AllInspectionPhotos aip = new AllInspectionPhotos();

    var folders = await ApplicationData.Current.LocalFolder.GetFoldersAsync();

    if (isOn)
    {
        foreach (var item in folders)
        {
            if (item.Name == "ONLINE")
            {
                var inspectionFolders = await item.GetFoldersAsync();

                foreach (var inspectionFolder in inspectionFolders)
                {
                    if (inspectionFolder.Name == chosen)
                    {
                        aip.InspectionEan = chosen;
                        var photos = await inspectionFolder.GetFilesAsync();

                        foreach (var photo in photos)
                        {
                            using (Stream stream = await photo.OpenStreamForReadAsync())
                            {
                                PhotoInspection phtInsp = new PhotoInspection();
                                var bytes = new byte[(int)stream.Length];
                                stream.Read(bytes, 0, (int)stream.Length);

                                phtInsp.Photo = bytes;

                                phtInsp.InspectionEan = chosen;

                                phtInsp.PhotoName = photo.Name;
                                aip.Photos.Add(phtInsp);
                            }
                        }
                    }
                }
            }
        }
    }
    else
    {
        foreach (var item in folders)
        {
            if (item.Name == "OFFLINE")
            {
                var inspectionFolders = await item.GetFoldersAsync();

                foreach (var inspectionFolder in inspectionFolders)
                {
                    if (inspectionFolder.Name == chosen)
                    {
                        aip.InspectionEan = chosen;
                        var photoset = await inspectionFolder.GetFilesAsync();

                        foreach (var photo in photoset)
                        {
                            PhotoInspection phtInsp = new PhotoInspection();

                            using (Stream stream = await photo.OpenStreamForReadAsync())
                            {
                                var bytes = new byte[(int)stream.Length];
                                stream.Read(bytes, 0, (int)stream.Length);

                                phtInsp.Photo = bytes;

                                phtInsp.InspectionEan = chosen;

                                phtInsp.PhotoName = photo.Name;
                            }
                            await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                            {
                                //await App._client.SendPhotoAsync(phtInsp);
                                aip.Photos.Add(phtInsp); //fires error here
                            });                                
                        }
                    }
                }
            }
        }
    }
    await App._client.SendAllPhotosAsync(aip);
}

然而,当我尝试将对象添加到列表中时,我得到"尝试读取写保护的内存"错误。 PhotoInspection对象填充了相关数据,在添加到列表之前一切都很好。谢谢你的帮助

1 个答案:

答案 0 :(得分:0)

问题是由于Dispatcher.RunAsync调用引起的,一旦aip.Photos.Add() lambda 排队,它就会将控制权返回给调用例程,而不是在它完成时。这导致aip对象在lambda实际运行之前被释放。

MSDN page for CoreDispatcher.RunAsync说:

  

[...]它在UI线程上安排工作并立即将控制权返回给调用者。

  

要从UI线程中剥离工作线程,请不要使用此方法(CoreDispatcher :: RunAsync)。相反,使用Windows :: System :: Threading :: ThreadPool :: RunAsync方法重载之一。

它还提供了以下代码示例,评论来自Microsoft!

//DO NOT USE THIS CODE.
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
   await signInDialog.ShowAsync(); 
});
// Execution continues here before the call to ShowAsync completes.