0

我有一个 Windows 窗体,里面有一个按钮和一个面板。

在按钮单击时,我正在向面板中添加一个控件……我想要多少就多少。此过程使用任务工厂。例子:

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 获取图像并将其放置在图片框中。

所以,场景是:

我多次按下按钮,我会立即看到自定义控件添加到面板中,但是每个控件的图片框都是空的,但是一旦工作人员从互联网加载图像并将其放在图片框上,图像就会开始出现.

关于如何实现这一点的任何线索?

非常感谢

4

3 回答 3

0

类似的东西:您不必异步添加控件。将它们添加到 GUI 线程中,并且每次创建一个新的工作线程,为它提供来自您的控件的委托,当工作人员完成加载图像时,该委托将被异步调用(使用 BeginInvoke?)。

于 2013-10-04T03:59:10.373 回答
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;
        } 

    }
于 2013-10-04T04:03:55.533 回答
0

我不太确定我是否理解你为什么将 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");
}
于 2013-10-04T04:12:52.573 回答