简体   繁体   English

如何在循环创建 UserControls 时解除对 UI 线程的阻塞?

[英]How to unblock the UI thread while UserControls are being created in a loop?

"RedditData" is a record where I keep a static field and property (UserClient) from which I get the FrontPage list (which in itself is a List of Post, and Post is a custom type). “RedditData”是我保留 static 字段和属性 (UserClient) 的记录,我从中获取 FrontPage 列表(它本身是 Post 列表,Post 是自定义类型)。 UserClient is of type RedditClient, from the Nuget package I use. UserClient 属于 RedditClient 类型,来自我使用的 Nuget package。

For now the code looks like this:目前,代码如下所示:

List<Post> list = new();

await Task.Run(() =>
{
   list = RedditData.UserClient.FrontPage;
});

foreach(Post post in await Task.Run (() => list))
{
  if(post is LinkPost linkPost)
  {
    UserControl userControl = new()
    {
      Title = linkPost.Title,
      Link = linkPost.Link,
      Button1ClickCommand = ICommandClick1,
      Button2ClickCommand = ICommandClick2
    };
    userControl.SetImage();
    ObservableCollectionOfUserControl.Add(userControl);
  }
  else if(post is SelfPost selfPost)
  {
     UserControl userControl = new()
    {
      Title = selfPost.Title,
      Link = selfPost.Link,
      Button1ClickCommand = ICommandClick1,
      Button2ClickCommand = ICommandClick2
    };
    //this list is used on the ItemsRepeater's ItemsSource x:Bind
    ObservableCollectionOfUserControl.Add(userControl);
  }
}

The problem with this code is that it blocks the UI while it's creating the UserControls.这段代码的问题是它在创建用户控件时阻塞了 UI。 I got to let it show the ProgressBar moving by using await Task.Run on the foreach, but it still blocks the window from moving, resizing, etc. I can't add the foreach inside a Task.Run or a Task.Factory.StartNew because of the UI creation, and even if I did put a foreach inside a dispatcher.TryEnqueue, it'd still block the UI thread.我必须通过在 foreach 上使用 await Task.Run 让它显示 ProgressBar 移动,但它仍然阻止 window 移动、调整大小等。我无法在 Task.Run 或 Task.Factory 中添加 foreach。 StartNew 因为创建了 UI,即使我确实在 dispatcher.TryEnqueue 中放置了一个 foreach,它仍然会阻塞 UI 线程。 I'm not sure what to do.我不知道该怎么办。

Two observations:两个观察:

Post, PostType1/2 are custom types from a Nuget package, Post,PostType1/2 是来自 Nuget package 的自定义类型,

ListOfPosts is not a local List and it's also from the Nuget package, although it is a "normal" List. ListOfPosts 不是本地列表,它也来自 Nuget package,尽管它是“正常”列表。 It's items are caught over the internet.它的物品是通过互联网捕获的。 I've tried passing them to a local variable before creating the UserControls, thinking it was something to do with the connection, but didn't change anything.在创建 UserControls 之前,我尝试将它们传递给局部变量,认为这与连接有关,但没有改变任何东西。

ListOfPosts is not a local List and it's also from the Nuget package, although it is a "normal" List. ListOfPosts 不是本地列表,它也来自 Nuget package,尽管它是“正常”列表。 It's items are caught over the internet.它的物品是通过互联网捕获的。 I've tried passing them to a local variable before creating the UserControls, thinking it was something to do with the connection, but didn't change anything.在创建 UserControls 之前,我尝试将它们传递给局部变量,认为这与连接有关,但没有改变任何东西。

This is almost certainly the problem right here.这几乎肯定是这里的问题。 I would try converting this custom list into a normal (in-memory) list within the Task.Run .我会尝试将此自定义列表转换为Task.Run中的普通(内存中)列表。 That way it won't be hitting the network on your UI thread.这样它就不会在您的 UI 线程上访问网络。

Depending on the implementation, you may also need to create your own DTO type(s) and copy the list entries over to them also off the UI thread.根据实现,您可能还需要创建自己的 DTO 类型并将列表条目复制到它们也离开 UI 线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM