Вы должны добавить свой динамический элемент управления в коллекцию элементов управления
int controlCounts = 0;
private void addControls_Click(object sender, EventArgs e)
{
controlCounts++;
TextBox txt_QTY = new TextBox();
txt_QTY.Location = new Point(100 * controlCounts, 100);
txt_QTY.Name = "txt_QTY" + controlCounts;
Controls.Add(txt_QTY);
txt_QTY.TextChanged += txt_QTY_TextChanged;
TextBox txt_Price = new TextBox();
txt_Price.Location = new Point(100 * controlCounts, 200);
txt_Price.Name = "txt_Price" + controlCounts;
Controls.Add(txt_Price);
txt_Price.TextChanged += txt_Price_TextChanged;
TextBox txt_Total = new TextBox();
txt_Total.Location = new Point(100 * controlCounts, 300);
txt_Total.Name = "txt_Total" + controlCounts;
Controls.Add(txt_Total);
}
private void txt_QTY_TextChanged(object sender, EventArgs e)
{
TextBox txt_QTY = (TextBox)sender;
string index = txt_QTY.Name.Substring("txt_QTY".Length);
updateTotal(index);
}
private void txt_Price_TextChanged(object sender, EventArgs e)
{
TextBox txt_Price = (TextBox)sender;
string index = txt_Price.Name.Substring("txt_Price".Length);
updateTotal(index);
}
private void updateTotal(string index)
{
TextBox txt_QTY = (TextBox)Controls["txt_QTY" + index];
TextBox txt_Price = (TextBox)Controls["txt_Price" + index];
TextBox txt_Total = (TextBox)Controls["txt_Total" + index];
if ((txt_QTY.Text != "") && (txt_Price.Text != ""))
{
txt_Total.Text = (Convert.ToInt32(txt_QTY.Text) * Convert.ToInt32(txt_Price.Text)).ToString();
}
}
. Это корректно, и описывает, как C# получает внешние переменные в закрытиях. Это не непосредственно проблема о параллелизме, а скорее об анонимных методах и лямбда-выражениях.
Этот вопрос обсуждает эту функцию языка и ее последствия подробно.
Ниже детализация ссылки, почему это происходит. Это записано для VB, но C# имеет ту же семантику.
http://blogs.msdn.com/jaredpar/archive/2007/07/26/closures-in-vb-part-5-looping.aspx
Это - обычное явление при использовании закрытий и особенно очевидно при построении запросов LINQ. Закрытие ссылается на переменную, не ее содержание, поэтому, чтобы заставить Ваш пример работать, можно просто указать переменную в цикле, который принимает значение t и затем ссылки это в закрытии. Это гарантирует, что каждая версия Вашего анонимного делегата ссылается на различную переменную.