以并行或并发方式向面板添加控件

时间:2013-06-07 21:16:37

标签: c# task-parallel-library

有一个面板我想添加k控件。我想为每个控件指定任务以供以后使用。所以:

*更新以下其他一些代码;请观看第三个代码 *

*****Update*****
    Child Control : PacketData (can be a Button)
    Main Control : panel
    PlaceData() changes the left and top randomly.

我这样做了:

        Parallel.For(0, k, (m) =>
        {
            tasks[m] = Task.Factory.StartNew(() =>
            {

                PacketData data = new PacketData();
                data.StartTime = sw.ElapsedMilliseconds;
                lock (data_adding_lock)
                {
                    IAsyncResult iar = panel1.BeginInvoke(new MethodInvoker(()=>{
                        PlaceData(ref data);
                        panel1.Controls.Add(data);
                    }));
                    panel1.EndInvoke(iar);
                    while (iar.IsCompleted ==false ) ;
                }


            });
        });

它的工作原理有时很好,但有时却没有,例如有时它只向面板添加一个PacketData 控制 。我是否放弃了比赛条件?

我也试过这个,但没有工作......

        Parallel.For(0, k, (m) =>
        {
            tasks[m] = Task.Factory.StartNew(() =>
            {
                PacketData data;
                lock (data_instancing_lock) {
                 data = new PacketData();}
                data.StartTime = sw.ElapsedMilliseconds;

                    IAsyncResult iar = panel1.BeginInvoke(new MethodInvoker(()=>{
                        PlaceData(ref data);
                        lock(data_adder_lock){
                        panel1.Controls.Add(data);}
                    }));
                    panel1.EndInvoke(iar);


                //PlaceData(ref data);

            });
        });

* UPDATE * *

这是另一个例子(不起作用......)

object l1 = new object();
object l2 = new object();
private delegate void AdderDel(Button bb);
public Form1()
{
    InitializeComponent();
}
private void AddControl(Button x)
{
    lock (l2)
    {
        this.Controls.Add(x);
    }
}
private void Place(ref Button btn)
{
    Random rnd = new Random();
    int x = rnd.Next(0, this.Width-100);
    int y = rnd.Next(0, this.Height-100);
    btn.Left = x;
    btn.Top = y;
}

private void button1_Click(object sender, EventArgs e)
{
    int n = 5;
    Task[] t = new Task[n];
    AdderDel ad = new AdderDel(AddControl);
    Parallel.For(0, n, (k) =>
        {

            t[k] = Task.Factory.StartNew(() =>
            {
                Button b = new Button();

                b.Text = k.ToString();
                b.Height = 50;
                Place(ref b);


                this.BeginInvoke(ad, b);


            });

        });

}

为什么?

1 个答案:

答案 0 :(得分:0)

您的代码对于它正在尝试的内容来说太复杂了,特别是因为我认为在这里使用并行性没有任何优势。 (虽然你的真实代码中可能有某些原因,但很难从你的样本中得知。)我认为你不应该使用并行性,直到你了解它是如何工作的。应该避免使用试错法进行编程,因为这意味着您实际上并不了解自己的代码,因此会导致错误。

但是代码中的实际问题与并行性没有任何关系。这是你错误地使用Random。如果使用默认构造函数,则Random将以当前时间播种。这意味着如果您像往常一样短时间创建多个Random实例,它们将返回相同的数字序列。这意味着所有按钮放在表单上,​​除了它们都在同一个地方,所以你只看到其中一个。

解决此问题的最简单方法是在一个字段中只有一个Random实例,并且只能从UI线程访问它,或者在使用它时使用锁。

如果您的代码可以正常运行,您可以考虑将其发布到Code Review Stack Exchange以便对其进行审核,然后解释一下您实际尝试做什么。

相关问题