There is a situation in which it seems that the function is performed 2 times, but in fact it turns out that 2 times it only increases a certain counter. Why this happens to me is not entirely clear. I will cite the blocks of code that may be indirectly related to this function. I simplify the code a bit, removing obviously unimportant moments.
The function in which the counter is increased twice:
void SendedBlock(int counter, int counter2) { PMData _sendData = new PMData(pmd); //..... // Добавляет указанную функцию в пул задач(опишу его в кратце далее) // И именно в передаваемой функции счётчик уменьшается соответвенно PoolForAction.Add(FuncAction, _sendData); // Следующая строка увеличивается 2 раза, но не сразу SendedCounter++; Thread.Sleep(2000); } The function in which the counter is subtracted:
void FuncAction(object _params) { if (_params is MyType) { //...... //Вот тут счетчик вычитается но только 1 раз(далее объясню последовательность) SendedCounter--; } } The task in which the execution of this function is called:
MultyLevelSended MLS = new MultyLevelSended(); void TaskStart() { SendedCounter = 0; MLS.LVL1CancelToken = LocalCancelToken; MLS.LVL2CancelToken = SendedCancelToken.ToArray(); MLS.LVL1Count = Counts; MLS.AUpdate = i => { /// Некая функция в которой я проверяю нужно ли входить на второй уровень цикла. }; MLS.Run(SendedBlock); } MultyLevelSended: (just some kind of wrapper, maybe it plays a role)
public class MultyLevelSended { public int LVL1Count = 0; public int LVL2Count = 0; public CancellationTokenSource LVL1CancelToken = null; public CancellationTokenSource[] LVL2CancelToken = null; public Action<int> AUpdate = null; public void Run(Action<int,int> _aMain) { try { Task.Factory.StartNew(() => { for (int i = 0; i < LVL1Count; i++) { AUpdate?.Invoke(i); try { Task.Factory.StartNew(() => { for (int j = 0; j < LVL2Count; j++) { _aMain?.Invoke(i,j); } }, LVL2CancelToken[i].Token).Wait(); } catch { } } }, LVL1CancelToken.Token).Wait(); } catch { } } } PoolForAction.Add() in fact simply calls the Post() function for the Dataflow block, in which in fact all submitted functions are executed in turn.
So here. TaskStart launching the TaskStart function (which was previously called via Task.Run as a task), the counter is reset. then all the necessary moments are filled in for the cycle wrapper and it is actually launched for execution. Suppose that the main transferred function is executed 2 times (the second level of the counter will be equal to 2 m). It will be executed 1 time, increasing the counter accordingly 1 time and sending it to the Poole a function that reduces it by 1 when it is executed, it will also happen a second time. But after that (focusing on breakpoints) he will return to SendedCounter++ and will simply increase it 2 times in a row. Logically, if he increases the second time, then he must send the event to the pool for execution a second time, and the counter should decrease, but he does not do this, but only increases the 2d counter. What is the problem to understand I did not succeed. I would be grateful for the help.
UPD:
I slightly added a wrapper for the test, so that after exiting the loop, the called function becomes Null and is not executed:
try { test = _aMain; Task.Factory.StartNew(() => { for (int j = 0; j < LVL2Count; j++) { test?.Invoke(i,j); } test = null; }, LVL2CancelToken[i].Token).Wait(); } catch { } But it does not help. The code comes to test=null , and then returns back to test?.Invoke(i,j); and it is executed anyway, because again it is not equal to null
UPD 2:
I changed the code and removed the tasks from it, and wrote:
public void Run(Action<int, int> _aMain) { for (int i = 0; i < LVL1Count; i++) { if (!LVL1CancelToken.IsCancellationRequested) { if (AUpdate?.Invoke(i) ?? true) for (int j = 0; j < LVL2Count; j++) { if (!LVL2CancelToken[i].IsCancellationRequested) { Console.WriteLine("Прохождения внутреннего цикла " + j + " Внешний " + i); _aMain?.Invoke(i, j); } } } } } In order to verify the cause of the problem. But in this and that case, the scheme remains the same, the function is called twice, and already with the following index. Visually how this happens is all I portrayed in this image: 
As described above, this "overshoot" appears only if run without debugging , if you start and check it step by step, then in 98% of cases these 2 extra calls will not be.
SendedCounterinto a property, then you can set a breakpoint on the setter, and you will see who changes it a second time. - VladDMultyLevelSendedloop. I am on the basis of the log was about this sequence. Screen - BwehaaFox 2:57 pmAUpdate"gives the go-ahead" at the entrance to the second loop level for the element with index 1 . after which, in turn, it calls the main function (_aMain) in the loop, after which, even before exiting this cycle, the main function is called 2 more times, but already for the element with index 2 , that is, before checking viaAUpdateand before changing the counter , or rather immediately after the first 2x. - BwehaaFox