通过属性更新方法获取TaskCanceledException

时间:2019-03-27 23:09:36

标签: uwp properties async-await

我有以下XAML帮助器类,该类允许我根据键选择位图图像:

namespace GammaFour.Views.Controls
{
    using System;
    using Windows.Storage;
    using Windows.Storage.Streams;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Media.Imaging;

    /// <summary>
    /// Provides an image from a store.
    /// </summary>
    public class BitmapSourceSelector : BitmapSource
    {
        /// <summary>
        /// The Category DependencyProperty.
        /// </summary>
        public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register(
            "Category",
            typeof(string),
            typeof(BitmapSourceSelector),
            new PropertyMetadata(default(string)));

        /// <summary>
        /// The Dictionary DependencyProperty.
        /// </summary>
        public static readonly DependencyProperty DictionaryProperty = DependencyProperty.Register(
            "Dictionary",
            typeof(UriDictionary),
            typeof(BitmapSourceSelector),
            new PropertyMetadata(default(UriDictionary)));

        /// <summary>
        /// The Key DependencyProperty.
        /// </summary>
        public static readonly DependencyProperty KeyProperty = DependencyProperty.Register(
            "Key",
            typeof(string),
            typeof(BitmapSourceSelector),
            new PropertyMetadata(default(string), BitmapSourceSelector.OnKeyPropertyChanged));

        /// <summary>
        /// Gets or sets the category used to select the source for the icon.
        /// </summary>
        public string Category
        {
            get
            {
                return this.GetValue(BitmapSourceSelector.CategoryProperty) as string;
            }

            set
            {
                this.SetValue(BitmapSourceSelector.CategoryProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the dictionary of URIs.
        /// </summary>
        public UriDictionary Dictionary
        {
            get
            {
                return this.GetValue(BitmapSourceSelector.DictionaryProperty) as UriDictionary;
            }

            set
            {
                this.SetValue(BitmapSourceSelector.DictionaryProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the key used to select the source for the icon.
        /// </summary>
        public string Key
        {
            get
            {
                return this.GetValue(BitmapSourceSelector.KeyProperty) as string;
            }

            set
            {
                this.SetValue(BitmapSourceSelector.KeyProperty, value);
            }
        }

        /// <summary>
        /// Invoked when the effective property value of the Key property changes.
        /// </summary>
        /// <param name="dependencyObject">The DependencyObject on which the property has changed value.</param>
        /// <param name="dependencyPropertyChangedEventArgs">
        /// Event data that is issued by any event that tracks changes to the effective value of this property.
        /// </param>
        private static async void OnKeyPropertyChanged(
            DependencyObject dependencyObject,
            DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            // Extract the changed properties.
            string key = dependencyPropertyChangedEventArgs.NewValue as string;
            BitmapSourceSelector bitmapSourceSelector = dependencyObject as BitmapSourceSelector;

            // Select a source for the image based on the new key.
            if (!string.IsNullOrEmpty(key) && bitmapSourceSelector.Dictionary != null)
            {
                Uri uri = bitmapSourceSelector.Dictionary.GetUri(bitmapSourceSelector.Category, key);
                StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(uri);
                IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
                await bitmapSourceSelector.SetSourceAsync(stream);
            }
        }
    }
}

执行OnKeyPropertyChanged方法时,出现异常:

Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
A task was canceled.

此调用期间发生异常:

        await bitmapSourceSelector.SetSourceAsync(stream);

如果我将 SetSourceAsync 替换为 SetSource ,它将运行正常。异常是随机发生的,通常表明await不在Window线程上返回,但是我找不到强制它的方法。所以我有两个问题:

  1. 此代码有什么问题?为什么不等待(同步 版本似乎工作正常,它支持     假设该调用没有在正确的线程上返回)。
  2. 有人能更好地将位图资源与 一个值?从理论上讲,视图模型不应包含任何     View和Bitmap资源的知识显然是方面     视图。

编辑:朱尼(Nico Zhu)要求参加支持班。他们在这里:

UriCategory:

/// <summary>
/// A category of URIs.
/// </summary>
public class UriCategory : Dictionary<string, UriSource>
{
}

UriDictionary:

/// <summary>
/// A dictionary of URIs organized by category.
/// </summary>
public class UriDictionary : Dictionary<string, UriCategory>
{
    /// <summary>
    /// Gets the URI associated with the category, key keys.
    /// </summary>
    /// <param name="category">The category of the URIs.</param>
    /// <param name="key">The key for the URI.</param>
    /// <returns>The URI entered into the dictionary with the category, key index.</returns>
    internal Uri GetUri(string category, string key)
    {
        // This URI is returned if there's no matching entry for the keys.
        Uri uri = default(Uri);

        // Use the two dictionary levels to find the URI.
        UriCategory resourceCategory;
        if (this.TryGetValue(category, out resourceCategory))
        {
            UriSource resourceSource;
            if (resourceCategory.TryGetValue(key, out resourceSource))
            {
                uri = resourceSource.Uri;
            }
        }

        // The URI belonging to the compound key.
        return uri;
    }
}

这是XAML中的用法:

<!-- Metadata Image Dictionary -->
<dbcontrols:UriDictionary x:Key="MetadataImages">
    <dbcontrols:UriCategory x:Key="Small">
        <dbcontrols:UriSource x:Key="Alert"
                                Uri="ms-appx:///GammaFour.InvestmentManagement.Views/Assets/Small/Alert.png"/>
        <dbcontrols:UriSource x:Key="Blotter"
                                Uri="ms-appx:///GammaFour.InvestmentManagement.Views/Assets/Small/Blotter.png"/>
        <dbcontrols:UriSource x:Key="Folder"
                                Uri="ms-appx:///GammaFour.InvestmentManagement.Views/Assets/Small/Folder.png"/>
        <dbcontrols:UriSource x:Key="Portfolio"
                                Uri="ms-appx:///GammaFour.InvestmentManagement.Views/Assets/Small/Portfolio.png"/>
    </dbcontrols:UriCategory>
    <dbcontrols:UriCategory x:Key="Medium">
        <dbcontrols:UriSource x:Key="Alert"
                                Uri="ms-appx:///GammaFour.InvestmentManagement.Views/Assets/Medium/Alert.png"/>
        <dbcontrols:UriSource x:Key="Blotter"
                                Uri="ms-appx:///GammaFour.InvestmentManagement.Views/Assets/Medium/Folder.png"/>
        <dbcontrols:UriSource x:Key="Folder"
                                Uri="ms-appx:///GammaFour.InvestmentManagement.Views/Assets/Medium/Folder.png"/>
        <dbcontrols:UriSource x:Key="Portfolio"
                                Uri="ms-appx:///GammaFour.InvestmentManagement.Views/Assets/Medium/Portfolio.png"/>
    </dbcontrols:UriCategory>
</dbcontrols:UriDictionary>

这是使用图像字典显示基于键的图像的方法。这种设计使视图模型不需要任何视图知识即可显示带有数据的图像。

<Grid Height="160"
      Width="190">
        <Image.Source>
            <dbcontrols:BitmapSourceSelector Category="Medium"
                                             Dictionary="{StaticResource MetadataImages}"
                                             Key="{Binding ImageKey}"/>
        </Image.Source>
    </Image>
</Grid>

同样,如果您知道一种更好的方法将视图模型从视图中删除,我将不胜感激。

0 个答案:

没有答案