c# - 是否有用于将控件绑定(bind)到异步数据的明确定义的模式?

标签 c# .net wpf data-binding asynchronous

您能判断以下代码片段是否正确绑定(bind)到异步数据源吗?

虽然它似乎在工作,即:UI 不会卡住,但我不完全确定正确性,因为 MSDN 文档并没有真正谈论绑定(bind)到这些中的“异步”方法文档:

Binding.IsAsync

ObjectDataProvider.IsAsynchronous

<pages:HottestPageProxy x:Key="PageProxy" ></pages:HottestPageProxy>

<ObjectDataProvider x:Key="DataProviderArtists" IsAsynchronous="True"  ObjectInstance="{StaticResource PageProxy}"  MethodName="GetArtists">
    <ObjectDataProvider.MethodParameters>
        <system:String>Grabbing artists !</system:String>
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

(HottestPageProxy 对象是一个为控件提供数据的小 helper )

public class HottestPageProxy
{
    [UsedImplicitly]
    public async Task<ArtistsQuery> GetArtists([CallerMemberName] string memberName = "")
    {
        Console.WriteLine(memberName);
        string apiKey = App.GetApiKey();
        Task<ArtistsQuery> topHottt = Queries.ArtistTopHottt(new ArtistTopHotttParameters
        {
            ApiKey = apiKey,
            Results = 100,
            Buckets = new[] {ArtistTopHotttBuckets.Hotttnesss}
        });
        return (await topHottt);
    }
}

编辑:“等待topHottt”调用的方法

public static async Task<ArtistsQuery> ArtistTopHottt(ArtistTopHotttParameters parameters)
{
    if (parameters == null) throw new ArgumentNullException("parameters");
    return await Get<ArtistsQuery>(parameters);
}

private static async Task<T> Get<T>(Parameters parameters) where T : Query
{
    if (parameters == null) throw new ArgumentNullException("parameters");
    ValidateParameters(parameters);

    string url = parameters.GetQueryUrl();
    var value = new Uri(url);
    using (var client = GetHttpClient())
    using (var message = await client.GetAsync(url))
    {
        // fetch message content (removed)
        return GetQueryResultObject<T>(s);
    }
}

private static T GetQueryResultObject<T>(string json) where T : class
{
    // create T from Json string (removed)
    return t;
}

使用 AsyncEx 编辑

尽管现在的语法是:

,但可以使用您的库
<ItemsControl x:Name="ItemsControlTopHott"
    ItemsSource="{Binding ... Path=Artists.Result.Artists ...}">
</ItemsControl>

“Artists.Result.Artists”真的是您希望我使用的吗? :)

新的语法使它更加困惑,因为来源是:

public sealed class ArtistsQuery : Query
{
    public List<Artist> Artists { get; set; }
}

没什么大不了的,但如果我能避免这种语法那就太好了。

你说 .Result 可能会带来死锁,那么我在实现你的解决方案时是否遗漏了什么?

Artists.PropertyChanged 事件引发了以下消息:

  • 状态:RanToCompletion
  • 已完成:真
  • IsSuccessfullyCompleted:真
  • 结果:成功

我会尝试使用您在帖子中提到的 .ConfigureAwait(false),看看效果如何。

忘记提及,实际上我使用 .Result 的实现确实不会阻塞 UI,因为获得结果的典型时间是几秒钟;我会看到 UI 卡住。这似乎是对的......但我不确定它是否正确,因此我的问题。

最佳答案

正如其他人所指出的,WPF 类型中的“异步”成员与 async 无关。和 await .

你的绑定(bind)确实有问题;你的路径正在使用 Task.Result ,这将阻塞 UI 线程,直到查询完成。另外,using Result brings up the possibility of a deadlock我在我的博客上描述的。

我有另一个博客条目处理 async properties ,特别是如何将数据绑定(bind)到(逻辑上)异步的属性。我的AsyncEx library有一个type called NotifyTaskCompletion 这使您可以更自然地将数据绑定(bind)到异步 ​​Task .

所以,例如,你可以做这样的事情:

public class HottestPageProxy
{
  public HottestPageProxy()
  {
    Artists = NotifyTaskCompletion.Create(GetArtists());
  }

  public INotifyTaskCompletion<ArtistsQuery> Artists { get; private set; }

  private Task<ArtistsQuery> GetArtists()
  {
    string apiKey = App.GetApiKey();
    return Queries.ArtistTopHottt(new ArtistTopHotttParameters
    {
        ApiKey = apiKey,
        Results = 100,
        Buckets = new[] {ArtistTopHotttBuckets.Hotttnesss}
    });
  }
}

然后您可以数据绑定(bind)到 INotifyTaskCompletion<T> 上的多个不同属性, 包括 IsCompleted , ErrorMessage , 和 Result (它不会阻塞;如果任务未完成,它将返回 default(T))。

关于c# - 是否有用于将控件绑定(bind)到异步数据的明确定义的模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18710161/

相关文章:

c# - 在加密中丢失特殊的 unicode 字符 (C#)

c# - 以代码形式查看 XSD

c# - "The description for Event ID X in Source Y cannot be found."

c# - 一次修复所有打开的文件在 VS2017 中显示的所有 'Naming rule violation'

c# - filehelpers 中的可选引号

c# - 是否有从字符串转换为构造函数类型的 DI 框架?

c# - 如何在 DataGridview 中更改一个单元格的值以更改其他单元格的值

wpf - 绑定(bind)到 datacontext parent-WPF 的属性

c# - WPF:有没有办法进行内联格式化?

c# - 有什么方法可以检测到应用程序设置更改?