Hello, previously created a topic on the problem, but then I did not know what exactly is wrong. At the moment, I found out what the problem is, the threads in the method are created several times with the same parameters.

for (int t = 0; t <= tCount - 1; t++) { new Thread(() => { int id = t; bool DoMain = true; int c = int.Parse(arr.GetValue(0, t - 1).ToString()), c_ = int.Parse(arr.GetValue(1, t - 1).ToString()); string fw = null, model = null, type = null, link = null; int size = 0; int a_thread = a, b_thread = b; Task<bool> tryget = null; int f = 1; Console.WriteLine("CREATE THREAD " + id + " WITH PARAMS : C = " + c + " C_ = " + c_); while (DoMain) { try { iterCount.Invoke(new Action(() => { iterCount.Text = string.Format("Количество итераций : {0}", ++iCount); })); } catch { Console.WriteLine("ERROR ON 154"); } { link = string.Format("http://update.hicloud.com:8180/TDS/data/files/p3/s15/G{0}/g{1}/v{2}/f{3}/full/changelog.xml", a_thread, b_thread, c, f); //Console.WriteLine("THREAD " + id + " LINK " + link); tryget = TryGetV3(link); tryget.Wait(); if (tryget.Result) { fw = xmlGetModel(link); size = xmlGetSize(link); //============================Вносим данные в форму============================ try { foreach (string s in readModels) { if (fw.Contains(s)) { model = s; break; } } if (size > 1500000000) { type = "FULL"; } else { type = "OTA"; } dataGridView1.Invoke(new Action(() => { dataGridView1.Rows.Add(model, fw, type, link, "Download", a_thread, b_thread, c, f, id); })); firmwareCount.Invoke(new Action(() => { firmwareCount.Text = string.Format("Найдено прошивок : {0}", dataGridView1.Rows.Count); })); } catch { Console.WriteLine("ERROR ON 188"); } } link = null; } try { File.AppendAllText(filePath, string.Format(@"{0},{1},{2},{3},{4},{5}", dataGridView1.Rows[5].Cells[dataGridView1.Columns.Count].Value.ToString(), dataGridView1.Rows[6].Cells[dataGridView1.Columns.Count].Value.ToString(), dataGridView1.Rows[7].Cells[dataGridView1.Columns.Count].Value.ToString(), dataGridView1.Rows[8].Cells[dataGridView1.Columns.Count].Value.ToString(), dataGridView1.Rows[1].Cells[dataGridView1.Columns.Count].Value.ToString(), dataGridView1.Rows[9].Cells[dataGridView1.Columns.Count].Value.ToString()) + Environment.NewLine); } catch { } //FOR V LOOP ++c; if (c < c_) DoMain = true; else DoMain = false; fw = null; model = null; type = null; link = null; size = 0; tryget = null; } }){IsBackground = true}.Start(); } 

Print the line Console.WriteLine("CREATE THREAD " + id + " WITH PARAMS : C = " + c + " C_ = " + c_);

 CREATE THREAD 7 WITH PARAMS : C = 47306 C_ = 47356 CREATE THREAD 7 WITH PARAMS : C = 47306 C_ = 47356 CREATE THREAD 7 WITH PARAMS : C = 47306 C_ = 47356 CREATE THREAD 7 WITH PARAMS : C = 47306 C_ = 47356 CREATE THREAD 7 WITH PARAMS : C = 47306 C_ = 47356 CREATE THREAD 8 WITH PARAMS : C = 47357 C_ = 47407 CREATE THREAD 8 WITH PARAMS : C = 47357 C_ = 47407 CREATE THREAD 8 WITH PARAMS : C = 47357 C_ = 47407 CREATE THREAD 11 WITH PARAMS : C = 47510 C_ = 47560 CREATE THREAD 11 WITH PARAMS : C = 47510 C_ = 47560 CREATE THREAD 11 WITH PARAMS : C = 47510 C_ = 47560 

Those. several identical flows are created with the same parameters, why is this happening? How can you deal with this?

    1 answer 1

    You have a whole bunch of poorly readable code here, but I would venture to suggest that the problem is in capturing the loop variable of the lambda function. Try writing this:

     for (int counter = 0; counter <= tCount - 1; counter++) { int t = counter; new Thread(() => { ....... }); } 

    A few words about what it is. The fact is that any lambda function in C # is implicitly converted by the compiler to a class, with the method representing the body of the lambda function. At the same time, if lambda captures some external variables, that is, its body uses variables from a code external to the lambda (in your case it is the for loop parameter t and a number of other variables), then in this backstage class they become fields . Accordingly, until the lambda completes its work, the captured variables will live (even if the external method is already completed). In the case of cycle counters (in your case, this is a cycle counter of int type), the following happens: the captured counter also becomes a member of this “invisible” class, and with each new iteration it is passed to the lambda not by value, but by reference. The cycle is very fast executed, incrementing the counter value and creating an unlimited number of threads, while the threads themselves do not have time to execute, and all of them (or almost all) use the last value of the counter, since they take it from the captured variable.

    This is a completely natural behavior, but it is completely unobvious. Therefore, it was fixed in C # 5. However, if you use an earlier version of the language, then you need to take into account this feature (which, incidentally, is kindly suggested by Resharper). Here is a good article on this topic. However, it has already been recommended in the comments.

    • thank you so much, it really helped - just_koala
    • I will add the answer to the link, it is useful to read: habrahabr.ru/post/141270 - andreycha