StorageFile 的 ValueConverter => 图片

ValueConverter for StorageFile => Image

我正在尝试将 MVVM 用于通用 Windows 项目,但存储文件的接口对使用异步有很多抱怨。以下代码有时有效:

    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var storageFile = value as StorageFile;
        return GetImageAsync(storageFile).Result;
    }

    private static async Task<ImageSource> GetImageAsync(StorageFile storageFile)
    {
        var bitmapImage = new BitmapImage();
        var stream = await storageFile.OpenAsync(FileAccessMode.Read).AsTask().ConfigureAwait(false);
        bitmapImage.SetSource(stream);
        return bitmapImage;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return null;
    }
}

直到我 select 加载新图像,然后我收到错误“{"The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))"}”

所以我尝试将其更改为每个线程使用 CoreDispatcher:

public class FileToImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var storageFile = value as StorageFile;
        Task<ImageSource> image = null;
        Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            image = GetImageAsync(storageFile);
            image.RunSynchronously();
        });

        return image.Result;
    }

    private static async Task<ImageSource> GetImageAsync(StorageFile storageFile)
    {
        var bitmapImage = new BitmapImage();
        var stream = await storageFile.OpenAsync(FileAccessMode.Read).AsTask().ConfigureAwait(false);
        bitmapImage.SetSource(stream);
        return bitmapImage;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return null;
    }
}

位图图像出现 NullReferenceException。这对我来说当然是绝对有意义的——异步调度程序将控制权让给父进程,图像尚未分配,空引用异常。但是我不知道怎样才是正确的做法!

感谢 Clemens 对 OP 的评论,这让我意识到我对模式很着迷,专注于使用我喜欢的东西而不是做正确的设计。

导致该问题的来源是:

    private async void GetFile()
    {
        var filePicker = new FileOpenPicker();
        filePicker.FileTypeFilter.Add(".jpg");
        filePicker.FileTypeFilter.Add(".png");
        filePicker.FileTypeFilter.Add(".gif");
        filePicker.FileTypeFilter.Add(".bmp");
        filePicker.ViewMode = PickerViewMode.Thumbnail;
        filePicker.SuggestedStartLocation = PickerLocationId.Desktop;
        filePicker.CommitButtonText = "Open";
        CurrentFile = await filePicker.PickSingleFileAsync(); //Bad code used CurrentFile set and NotifyPropertyChanged to start up the value converter code from OP

        //New, obvious better code            
        CurrentImage = await GetImageSource(CurrentFile);

        var statistics = new ImageStatistics();

        Logger.Log("Metadata start");
        var data = statistics.GetMetaData(CurrentFile);

        Logger.Log("Color Counts start");
        var colorCounts = statistics.GetColorCounts(CurrentFile);

        var filterer = new ColorFilterer();
        Logger.Log("Color Counts await start");
        var filteredColors = filterer.GetTopColors(await colorCounts, 10);
        Logger.Log("Color Counts await end");

        Logger.Log("Metadata await start");
        var metaData = await data;
        Logger.Log("Metadata await end");

        Make = metaData[SystemProperty.CameraManufacturer];
        Model = metaData[SystemProperty.CameraModel];
        ExposureTime = string.Format("1/{0}",1/Convert.ToDouble(metaData[SystemProperty.ExposureTime]));
        ISOSpeed = metaData[SystemProperty.ISOSpeed];
        FStop = string.Format("f/{0}", metaData[SystemProperty.FStop]);
        ExposureBias = metaData[SystemProperty.ExposureBias];

        TopColors = filteredColors.Select(pair => new ColorStatistics { Color = pair.Key, Count = pair.Value }).ToList();
    }

所以我只是在选择图像后继续执行我想要的操作。这里还有很多需要解决的问题,特别是因为我在执行工作时阻塞了 UI,并且没有通过将这些其他 UI 组件订阅到 属性 来委托这些操作,但这是一个开始,没有更多例外!

注意这里没有包含,值转换器已经从主应用层移除。