我有一个Windows窗体,里面有一个Button和一个Panel。
在按钮上单击我正在向面板添加控件...尽可能多。此过程正在使用任务工厂。例如:
private void ButtonClick()
{
// This line needs to happen on the UI thread...
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
CustomControl.PersonResult newControl = new CustomControl.PersonResult();
this.panel1.Controls.Add(newControl);
}, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
}
我的PersonResult.cs控件具有以下布局:
该控件有一个图片框和3个标签。
现在,当一个新的 PersonResult 控件添加到表单中时,我想执行其他后台工作程序,以便从Internet获取图像并将其放在图片框中。
所以,情景是:
我多次按下按钮,我会立即看到自定义控件添加到面板中,但每个控件的图片框都是空的,但是一旦工作人员从互联网加载图像并将其放置,图像就会立即显示在图片框上。
有关如何实现这一点的任何线索?
非常感谢
答案 0 :(得分:0)
有些事情: 您不必异步添加控件。将它们添加到GUI线程中,每次创建一个新的工作线程,为其提供来自控件的委托,当工作人员完成加载图像时,将委托异步调用(使用BeginInvoke?)。
答案 1 :(得分:0)
每次触摸控件时都必须从UI线程执行此操作。您可以从线程/任务中实际下载图片和其他长时间运行的任务。从您的线程中,您使用Control.Invoke在UI线程上调用委托。
这篇MSDN文章提供了一个使用Control.Invoke和一些简单变量(如字符串等)的好例子:
http://msdn.microsoft.com/en-us/library/a1hetckb(v=vs.100).aspx
但是通常使用辅助类,因此您可以在代理之间传递更复杂的数据,而无需使用大讨厌的对象数组。
以下是我做过的一些示例代码:
private void button1_Click(object sender, EventArgs e) {
Task.Factory.StartNew(() =>
{
DataClass dataClass = new DataClass(this.textBox1);
Thread.Sleep(5000); // simulate long running task
dataClass.TextToPass = "set some text";
dataClass.updateTargetControl();
});
}
private class DataClass {
delegate void updateTextBoxOnUiThreadDelegate();
private TextBox _targetControl= null;
private updateTextBoxOnUiThreadDelegate _updateDelegate;
internal DataClass(TextBox targetControl) {
_updateDelegate = new updateTextBoxOnUiThreadDelegate(updateOnUiThread);
_targetControl = targetControl;
}
internal string TextToPass = "";
internal void updateTargetControl() {
_targetControl.Invoke(_updateDelegate);
}
private void updateOnUiThread() {
_targetControl.Text = this.TextToPass;
}
}
答案 2 :(得分:0)
我不太清楚我理解为什么你在自己的Task中包装了一个UI操作..当它没有链接到异步任务时。
无论如何.. PictureBoxes有一个LoadAsync方法。为什么要比实际需要更难?
private void ButtonClick()
{
CustomControl.PersonResult newControl = new CustomControl.PersonResult();
this.panel1.Controls.Add(newControl);
newControl.PictureBox.WaitOnLoad = false;
newControl.PictureBox.LoadAsync("http://url-here.com/image.jpg");
}