从 UI 线程以外的其他线程将控件添加到流布局面板



我试图使用循环从主线程以外的其他线程向 flowlayoutpanel 添加一些控件,但我做不到。有什么帮助吗? 此代码在 UI 线程上运行

private bool ShowProducts(string Page ,string KeyWord)
{
string Res = AO.GetPageInfo(Page ,textBox1.Text);
if(Res == ""){
return false;
}
label12.Text = Res;
CurrentPage = int.Parse(Page);
textBox3.Text = Page;
//flowLayoutPanel2.Visible = false;
flowLayoutPanel2.Controls.Clear();
Products = AO.SearchProducts(CurrentPage.ToString(), textBox1.Text);
foreach(Product X in Products)
flowLayoutPanel2.Controls.Add( new Card(X) );
return true;
}

问题是,对于如此长时间运行的操作,您希望使用async/await.代码看起来或多或少如下所示:

private async Task<bool> ShowProducts(string page, string keyWord)
{
string text = textBox1.Text;
string res = await Task.Run(() => AO.GetPageInfo(page, text)); //run on a thread pool
if(res == "")
{
return false;
}
label12.Text = res;
CurrentPage = int.Parse(page);
textBox3.Text = page;
//flowLayoutPanel2.Visible = false;
flowLayoutPanel2.Controls.Clear();
Products = await Task.Run(() => AO.SearchProducts(CurrentPage.ToString(), text)); //run on a thread pool
//foreach(Product X in Products)
//    flowLayoutPanel2.Controls.Add(new Card(X));
//This code will block only for the time of adding the controls.
//This is unavoidable as flowLayoutPanel2 is part of the UI 
//and has to be updated on the UI thread.
//Making the controls is done on a thread pool so it won't block
flowLayoutPanel2.Controls.AddRange(await Task.Run(() => Products.Select(x => new Card(x)).ToArray()));
return true;
}

这将允许 UI 线程在函数执行时工作。但是你必须像这样运行它

bool result = await ShowProducts("1", "keyWord");

因此,您必须从async方法调用它。我建议您阅读它们并在代码中实现它们。


一些资源:

斯蒂芬·克利里的介绍 - 它很老了,但仍然相关

Microsoft文档

关于async/await的堆栈溢出问题

如果你想从另一个线程在UI线程中做一些事情,你必须调用你想要做的事情。

然后,您可以像这样轻松"控制":

this.Invoke((MethodInvoker)delegate {
Button button = new Button();
myFlowLayoutPanel.Controls.Add(button);
});

希望这对你有帮助。

最新更新