【问题标题】:How to make a File Exists Converter in WinRT如何在 WinRT 中制作文件存在转换器
【发布时间】:2012-08-25 03:35:06
【问题描述】:

我正在尝试使用转换器检查本地存储中是否存在图像源。如果不使用外部网址。

<Image Source="{Binding Image, Converter={StaticResource ImageCacheConverter}}"/>

到目前为止,这是我的转换器:

public object Convert(object value, Type targetType, object parameter, string language)
{
    return IfFileExist((string)value, "localimage.png");
}
public async Task<string> IfFileExist(string value, string filename)
{
    var folder = ApplicationData.Current.LocalFolder;
    var getFilesAsync = await folder.GetFilesAsync(CommonFileQuery.OrderByName);

    var file = getFilesAsync.FirstOrDefault(x => x.Name == filename);
    if (file != null)
    {
        return "ms-appdata:///local/" + filename;
    }
    return (string)value;
}

我面临的主要问题是 IValueConverter 内部有异步。但我需要返回 IfFileExist 来更改图像源。

提前致谢。

【问题讨论】:

  • 为什么还是IfFileExist async
  • 导致等待文件夹.GetFilesAsync(CommonFileQuery.OrderByName);
  • 您确定要将一个可能很慢的操作作为绑定的一部分吗?如果文件被移动,我会缓存信息并添加一些错误处理。这个方法是有原因的async!
  • 我正在尝试检查图像是否缓存在本地存储中。它应该是一个正常的转换器工作。我是 C# 新手。

标签: c# xaml windows-runtime converter


【解决方案1】:

我认为您不希望您的 IfFileExist 方法异步运行。但这就是因为await 的使用而发生的事情。

尝试将其更改为:

public async Task<System.Collections.Generic.IReadOnlyList<Windows.Storage.StorageFile>> GetFilesAsync()
{
    var folder = ApplicationData.Current.LocalFolder;
    return await folder.GetFilesAsync(CommonFileQuery.OrderByName)
                       .AsTask().ConfigureAwait(false);
}

public string IfFileExist(string value, string filename)   
{   
    var files = GetFilesAsync().Result;

    var file = files.FirstOrDefault(x => x.Name == filename);   
    if (file != null)   
    {   
        return "ms-appdata:///local/" + filename;   
    }   
    return value;   
}

我们不是使用await,而是访问GetFilesAsync返回的任务的Result属性,阻塞我们的方法直到任务完成。

您的原始代码与以下代码类似:

public async Task<string> IfFileExist(string value, string filename) 
{ 
    var folder = ApplicationData.Current.LocalFolder; 
    var getFilesAsync = folder.GetFilesAsync(CommonFileQuery.OrderByName); 

    return getFilesAsync.ContinueWith(z => 
    {
        var file = getFilesAsync.FirstOrDefault(x => x.Name == filename); 
        if (file != null) 
        { 
            return "ms-appdata:///local/" + filename; 
        } 
        return (string)value; 
    }
} 

【讨论】:

  • 转换器返回错误:'await' 运算符只能在异步方法中使用。考虑使用 'async' 修饰符标记此方法并将其返回类型更改为 'Task'
  • A 收到此错误:'Windows.Foundation.IAsyncOperation>' 不包含 'Result' 的定义并且没有扩展方法'可以找到接受“Windows.Foundation.IAsyncOperation>”类型的第一个参数的“结果”(您是否缺少 using 指令或程序集引用?)
  • @nicruo:请查看更新。我没有使用Windows.Foundation.IAsyncOperation 的经验,所以可能有更简单的方法来做到这一点。
  • 感谢您的帮助,但现在我的应用程序进入 GetFilesAsync() 但始终没有出来。
  • 此解决方案导致deadlock problem I describe here
【解决方案2】:

核心问题是您需要在同步操作(Convert)中执行async 操作。没有简单的方法可以做到这一点。如果可能,将您的代码结构化为不必要的(例如,让一个属性启动 async 更新到另一个属性,这是“转换”的结果)。

如果你想尝试强制它适应,你必须使用ConfigureAwait(false)

public object Convert(object value, Type targetType, object parameter, string language)
{
  // Note that "Result" will wrap any errors in AggregateException, which is annoying.
  return IfFileExist((string)value, "localimage.png").Result;
}

public async Task<string> IfFileExist(string value, string filename)
{
  var folder = ApplicationData.Current.LocalFolder;
  var getFilesAsync = await folder.GetFilesAsync(CommonFileQuery.OrderByName)
      .AsTask().ConfigureAwait(false);

  var file = getFilesAsync.FirstOrDefault(x => x.Name == filename);
  if (file != null)
  {
    return "ms-appdata:///local/" + filename;
  }
  return (string)value;
}

【讨论】:

  • 收到此错误:“Windows.Foundation.IAsyncOperation>”不包含“StartAsTask”的定义,也没有扩展方法“StartAsTask” ' 可以找到接受“Windows.Foundation.IAsyncOperation>”类型的第一个参数(您是否缺少 using 指令或程序集引用?)
  • 谢谢伙计。你导致正确的答案。 Daniel Hilgarth 做到了。抱歉,我无法将你们俩都选为正确答案。
【解决方案3】:

我现在附近没有 Windows 8,但我可能建议尝试以下代码(只是 Convert 方法体):

public object Convert(object value, Type targetType, object parameter, string language)   
{
    string result = string.Empty;
    Task.Run(async delegate
    {
        result = await IfFileExist((string)value, "localimage.png");
    }).Wait();

    return result;
}

我不确定它是否有效。

【讨论】:

  • 嗨亚历山大,对不起,我没有回答你。我试过了,但没有用。不过还是感谢您的宝贵时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-11
  • 1970-01-01
  • 2014-02-05
  • 1970-01-01
  • 2018-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多