-1

有一个面板,我想向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向面板 Control 添加一个。我失去了比赛条件吗?

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

        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);

            });
        });

*更新* *

这是另一个例子(它不工作......)

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);


            });

        });

}

为什么?

4

1 回答 1

0

您的代码对于它试图做的事情来说太复杂了,特别是因为我没有看到在这里使用并行性有任何优势。(虽然在你的真实代码中可能有一些原因,但很难从你的示例中分辨出来。)我认为你不应该使用并行性,直到你了解它是如何工作的。并且应该避免使用试错法进行编程,因为这意味着您实际上并不了解自己的代码,因此会导致错误。

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

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

如果您的代码可以正常工作,您可能会考虑将其发布到Code Review Stack Exchange以对其进行审核,并说明您实际尝试执行的操作。

于 2013-06-08T11:49:12.093 回答