使用在线程中创建的控件

时间:2016-10-28 17:36:36

标签: c# multithreading winforms dynamic-controls

您好我正在尝试将另一个具有文本框Arraylist的类中的方法调用到主窗体中的面板中,目前它可以正常工作但是我需要放置方法

我已经尝试了

ThreadStart starter = () => draw.DynamicTextBox(c, f);
Thread thread = new Thread(starter);
thread.Start();

但它给我的对象引用未设置为对象异常的实例或Arraylist为null

//Code in MainForm
public generator draw = new generator();
private void Button1_Click(object sender, EventArgs e)
    {
        int c = Convert.ToInt16(txbColumn.Text);
        int f = Convert.ToInt16(txbRow.Text);

        draw.DynamicTextBox(c, f); //needs to be on a Thread

        foreach (Control txtb in draw.textboxList)
        {
            Paneltxb.Controls.Add(txtb); 
        }

    }

//Code in Generator Class
 public class generator
{
    public ArrayList textboxList;


    public void DynamicTextBox(int c, int f )
    {
        textboxList = new ArrayList();
        int n = 0;
        for (int x = 0; x < f; x++)
        {
            for (int y = 0; y < c; y++)
            {
                        n++;
                        TextBox txtb = new TextBox();
                        txtb.Text = "txb " + n;
                        txtb.Name = "txb" + n;

                        txtb.Location = new Point(y * 100, x * 20);
                        textboxList.Add(txtb);

            }

        }
    }


}

2 个答案:

答案 0 :(得分:3)

它告诉你ArrayList为null,因为 ArrayList为null 。在那个时间点。

    ThreadStart starter = () => draw.DynamicTextBox(c, f);
    Thread thread = new Thread(starter);
    thread.Start();

    //  The thread just started running. The textboxes have not been created yet. 
    //  draw.textboxList has not been given a value yet. It's null.
    //  The stuff in the other thread is happening in a different thread, 
    //  at its own pace. 
    //  The whole point of putting it in another thread is that the rest of the code 
    //  in *this* thread continues executing before the other thread finishes. You can't
    //  ever make any assumptions about when stuff in another thread happens, unless you 
    //  write code to explicitly synchronize the two, which is a proverbially tricky 
    //  business. 

    foreach (Control txtb in draw.textboxList)
    {
        Paneltxb.Controls.Add(txtb); 
    }

如果你想等到使用另一个线程的结果,直到它完成创建它们,最明显的方法是确保发生这种情况只是在另一个线程中进行。尝试这样的事情:

ThreadStart starter = () => {
    draw.DynamicTextBox(c, f);

    //  We do this Invoke thing because we're messing with UI, which has to 
    //  be done in the UI thread. We're in another thread, so what Invoke
    //  does for us is it reaches into the UI thread and executes its code 
    //  there. It does this using magic thread runtime pixies or something. 
    //  I don't know what. 
    this.BeginInvoke(new MethodInvoker(delegate {
        foreach (Control txtb in draw.textboxList)
        {
            Paneltxb.Controls.Add(txtb); 
        }
    });
};

我怀疑,无论如何都会爆炸,因为你正在从UI线程中创建TextBoxes。祝好运。

答案 1 :(得分:0)

你可以尝试async / await(见下文)但是我不确定通过Task.Run()使用新线程是否值得,因为它似乎不需要“并行化”工作:

private async void Button1_Click(object sender, EventArgs e)
{
    int c = Convert.ToInt16(txbColumn.Text);
    int f = Convert.ToInt16(txbRow.Text);

    await Task.Run(()=> draw.DynamicTextBox(c, f));

    foreach (Control txtb in draw.textboxList)
    {
        Paneltxb.Controls.Add(txtb); 
    }

}

public class generator
{
public ArrayList textboxList;
...
public void DynamicTextBox(int c, int f )
{
 ...
}...

}

我建议使用async / await模式的一个原因是在访问UI元素时不必担心dipatcher。 await之后的代码将在UI线程上运行,因为await会捕获UI同步上下文。