private int GetPseudoRandomBlock(float stepFactor, float theta2)
            {
                var startIdx = AsyncRandom.GetRandomBlockIdx(random, id, shared.BlockLock);

                var currentIdx        = startIdx;
                var currentBlockValue = GetMaxAbsBlockValue(shared, shared.ActiveSet[currentIdx], stepFactor, theta2);
                var searchLength      = (int)(shared.ActiveSet.Count / totalNodes * searchPercentage);

                for (int i = 1; i < searchLength; i++)
                {
                    var checkIdx = (startIdx + i) % shared.ActiveSet.Count;
                    if (Thread.VolatileRead(ref shared.BlockLock[checkIdx]) == 0)
                    {
                        //check if next block is better than current block
                        var checkBlockValue = GetMaxAbsBlockValue(shared, shared.ActiveSet[checkIdx], stepFactor, theta2);

                        if (currentBlockValue < checkBlockValue)
                        {
                            if (Interlocked.CompareExchange(ref shared.BlockLock[checkIdx], this.id, 0) == 0)
                            {
                                //locking of better block successful, continue
                                Thread.VolatileWrite(ref shared.BlockLock[currentIdx], 0);
                                currentIdx        = checkIdx;
                                currentBlockValue = checkBlockValue;
                            }
                            else
                            {
                                //some other thread conflicted with ours, jump to another random place
                                startIdx = random.Next(0, shared.ActiveSet.Count);
                            }
                        }
                    }
                }

                return(currentIdx);
            }