调用FlowLayoutPanel,防止UI在添加项目时冻结

时间:2014-04-02 15:23:15

标签: c# .net winforms asynchronous

基本上我尝试使用用户控件填充流布局面板,而UI仍然是反复的。

我正在构建一个服务器/客户端应用程序,它获取rss feed然后返回文章。我想用这些文章填充flowlayoutpanel,同时UI仍然响应。

目前我尝试过这样的事情:

            Subc(feedcodes); //this method sends codes to the server and gets responses.
            if (NewsItemsPanel.InvokeRequired)
            {
                NewsItemsPanel.Invoke((MethodInvoker)(() => popPanel()));
                //popPanel populates the panel with the news items;

            }

此时if / else从不执行if。我试过四处寻找但无法找到相关或近乎相关的帮助。上面的代码在点击按钮内。

这是popPanel方法:

    private void popPanel()
    {
        try
        {
            feedsPanel.Controls.Clear();
            foreach (NewsItem item in News.getNewsItems())
            {
                usercontrolNewsItem rssitem = new usercontrolNewsItem (item.title, item.summary);
                feedsPanel.Controls.Add(rssitem);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error");
        }
    }

任何帮助都会很棒:)

感谢

1 个答案:

答案 0 :(得分:0)

单击按钮时,其事件在UI thread =>中上升没有InvokeRequired。您的长时间运行的代码应该在UI线程之外执行,在您更新内容时,从您调用的位置执行UI线程。

例如,

private void button1_Click(object sender, EventArgs e)
{
    panel.Clear(); // *see Hans comment
    (new Thread(LongRunningMethod)).Start();
}

private void LongRunningMethod()
{
    // ... retrieve items

    Invoke(() =>
    {
        // ... add items to panel
    });
}

然而,我推荐这个设计

private void LongRunningMethod()
{
    while(thereAreMoreItems)
    {
        // ... retrieve next item

        Invoke(() =>
        {
            // ... add item to panel
        });
    }
}

如果有很多项目,那么最好在虚拟模式下使用一个列表控件。创建数百个控件很糟糕。加载数百万项数据,如果用户一次只能看到100,那就太糟糕了。