How can I dequeue all values in a Queue? In the following code when I try to do so loop stops in the middle. I don't understand.
Queue<int> integers = new Queue<int>();
for (int i = 0; i < 20; i++)
{
integers.Enqueue(i);
}
Console.WriteLine(integers.Count); // 20
Console.WriteLine();
for (int i = 0; i < integers.Count; i++)
{
Console.WriteLine(integers.Dequeue()); // Stops at 10
}
Console.WriteLine();
Console.WriteLine(integers.Count); // 10
Your integers.Count is decreasing every time you dequeue, so after ten iterations of your for loop, it will be at 10, so the loop will exit.
For your code to work, just save the length of your queue before the loop, like so:
var length = integers.Count;
for (int i = 0; i < length; i++)
{
Console.WriteLine(integers.Dequeue());
}
edit: Above solution is with minimal changes to OP's code. As per suggestions in the comments (and other answers), a while loop is generally more recommended for this type of task:
while (integers.Count != 0) {
Console.WriteLine(integers.Dequeue());
}
Just change the loop to be:
while(integers.Count > 0) { Console.WriteLine(integers.Dequeue()); }
You are removing items from queue when you dequeue.
Try this: https://dotnetfiddle.net/FbXgoA
Queue<int> integers = new Queue<int>();
for (int i = 0; i < 20; i++)
{
integers.Enqueue(i);
}
Console.WriteLine(integers.Count); // 20
Console.WriteLine();
while(integers.Count > 0)
{
Console.WriteLine(integers.Count + ": " + integers.Dequeue());
}
Console.WriteLine();
Console.WriteLine(integers.Count); // 0
The issue is that as you dequeue the integers, integers.Count is also updated at the same time.
Thus, by the middle of the queue, i = 10 and also integers.Count = 10, so the for loop exits.
Try this:
while (integers.Count > 0)
{
Console.WriteLine(integers.Dequeue());
}
Related
I have this variable called tasks:
var tasks = new List<string>();
Right now tasks has a count of 81, but this could change down the road.
What I am trying to do is 3 loops of tasks getting 28 at a time like so:
#for (var i = 0; i < 28; i++)
{
}
#for (var i = 28; i < 56; i++)
{
}
#for (var i = 56; i < 81; i++)
{
}
I do not like that I hard coded the numbers, so my question is using tasks.Count What would be the best way loop through an array getting 28 at a time?
Since you have clarified in the comments that what you really want to do is do something different after each block of 28 (or whatever) elements. For that you can make use of the % operator. For example:
//Keep this constant somewhere else or maybe in a config value so it is easily changed
private const int TasksPerPage = 28;
And now we can loop over your data while outputting a page break after 28 elements:
for(var i = 0; i < tasks.Count(); i++)
{
//You can remove the i>0 check if you want to output a break at the start
if (i % TasksPerPage == 0 && i > 0)
{
Console.WriteLine("Page Break");
}
Console.WriteLine(tasks[i]);
}
You can use Linq to take & skip a specific amount.
var tasks = new List<string>();
var groupSize = tasks.Count() / 3;
var groupOne = tasks.Take(groupSize);
var groupTwo = tasks.Skip(groupSize).Take(groupSize);
var groupThree = tasks.Skip(groupSize * 2).Take(groupSize);
foreach(var item in groupOne)
{
// Do Something
}
foreach(var item in groupTwo)
{
// Do Something
}
foreach(var item in groupThree)
{
// Do Something
}
This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 11 months ago.
My program is running tasks in groups of n tasks at once each time.
Each task writes data to a Queue<string> object of his own, provided by an index to a Queue<string> in a List<Queue<string>> of queues.
the tasks do not share data or Queues, yet I still get synchronization errors.
I know the data structures are not Thread-Safe, I don't understand why they should be, and why I get the errors, since each Task has his own data structure, what could cause the errors?
here is a simple code to demonstrate:
class Program
{
static int j = 0;
List<Queue<string>> queueList = new List<Queue<string>>();
public void StartTasts(int n)
{
for (int i = 0; i < n; i++)
queueList.Add(new Queue<string>());
List<Task> tsk = new List<Task>();
for (int TaskGroup = 0; TaskGroup < 10; TaskGroup++)
{ //10 groups of task
//each group has 'n' tasks working in parallel
for (int i = 0; i < n; i++)
{
//each task gets its own and independent queue from the list
tsk.Add(Task.Factory.StartNew(() =>
{
DoWork(j % n);
}));
j++;
}
//waiting for each task group to finish
foreach (Task t in tsk)
t.Wait();
//after they all finished working with the queues, clear queues
//making them ready for the nest task group
foreach (Queue<string> q in queueList)
q.Clear();
}
}
public void DoWork(int queue)
{
//demonstration of generating strings
//and put them in the correct queue
for (int k = 0; k < 10000; k++)
queueList[queue].Enqueue(k + "");
}
static void Main(string[] args)
{
new Program().StartTasts(10);
}
}
this program generate some errors such as:
System.ArgumentException: 'Destination array was not long enough. Check destIndex and length, and the array's lower bounds.'
System.IndexOutOfRangeException: 'Index was outside the bounds of the array.' (at the Queue)
System.AggregateException: One or more errors occurred. ---> System.ArgumentException: Source array was not long enough. Check srcIndex and length, and the array's lower bounds.
and more errors and would not come up on a Serial case.
I would love to understand why because I cant see how these tasks mess up each other's independent Queues.
The problem is normal variable closure issues. Because all tasks share the same instance of the variable j they will all share the same value, most likely what is happening is your loop starts up 10 tasks super quick, but before any of them can get to j % n the value of j has already become 10.
Make a local copy of k that is declared within the scope of the for loop and it should solve your problem.
public void StartTasts(int n)
{
for (int i = 0; i < n; i++)
queueList.Add(new Queue<string>());
List<Task> tsk = new List<Task>();
for (int TaskGroup = 0; TaskGroup < 10; TaskGroup++)
{ //10 groups of task
//each group has 'n' tasks working in parallel
for (int i = 0; i < n; i++)
{
int k = j; // `int k = i;` would work here too and give you the same results.
tsk.Add(Task.Factory.StartNew(() =>
{
DoWork(k % n);
}));
j++;
}
//waiting for each task group to finish
foreach (Task t in tsk)
t.Wait();
//after they all finished working with the queues, clear queues
//making them ready for the nest task group
foreach (Queue<string> q in queueList)
q.Clear();
}
}
If you want to see the problem in action with a simpler recreation, try this simple code instead.
public static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
int j = i;
Task.TaskFactory.StartNew(() =>
{
Thread.Sleep(10); //Give a little time for the for loop to complete.
Console.WriteLine("i: " + i + " j: " + j);
}
});
Console.ReadLine();
}
You have calculated the taskId inside of the task and changed the base for the calculation outside of the task.
I have changed the logic only slightly. I have not had any errors.
namespace Project1
{
using System.Collections.Generic;
using System.Threading.Tasks;
internal class Program
{
private static int j = 0;
private readonly List<Queue<string>> queueList = new List<Queue<string>>();
public void StartTasts(int n)
{
for (var i = 0; i < n; i++)
{
this.queueList.Add(new Queue<string>());
}
var taskList = new List<Task>();
for (var taskGroup = 0; taskGroup < 10; taskGroup++)
{
// 10 groups of task
// each group has 'n' tasks working in parallel
for (var i = 0; i < n; i++)
{
// each task gets its own and independent queue from the list
var taskId = j % n;
taskList.Add(
Task.Factory.StartNew(
() =>
{
this.DoWork(taskId);
}));
j++;
}
// waiting for each task group to finish
foreach (var t in taskList)
{
t.Wait();
}
// after they all finished working with the queues, clear queues
// making them ready for the nest task group
foreach (var q in this.queueList)
{
q.Clear();
}
}
}
public void DoWork(int queue)
{
// demonstration of generating strings
// and put them in the correct queue
for (var k = 0; k < 10000; k++)
{
this.queueList[queue].Enqueue(k + string.Empty);
}
}
private static void Main(string[] args)
{
new Program().StartTasts(10);
}
}
}
I do not think you problem is in the que, it seems like it in the list itself might be an issue.
As the rule of using parallel or synchronous processes the list is not a thread save DS.
Try using the thread save DS Like ConcurrentBag Class
Excuse me for the silly question, but i can't manage to solve it.
How can i make something to happen every third time ?
Times(left number):
shipmentId=0
shipmentId=0
shipmentId=1
shipmentId=1
shipmentId=2
shipmentId=2 ....
int occurrence = 0;
int counter = 0;
foreach (var el in elmOrderData)
{
if (el.Name == "shipmentIndex")
{// we are entering here for every element that his name is "shipmentIndex"
el.SetValue(shipmentId);
secondTime++;
}
if ((secondTime % 2) == 0)
{// every third time we see "shipmentIndex"
secondTime = 1;
shipmentId++;
}
}
You could use a bool as in the following example. This will display messageboxes 1,3,5,7 and 9:
bool test = false;
for (int i = 0; i < 10; i++)
{
if (test)
MessageBox.Show(i.ToString());
test = !test;
}
Trying to piece together your notes - whether 'it' happens every time or not. How about this?
int occurrence = 0;
int counter = 0;
foreach(var a in list)
{
if(some_condition)
{
// do something..
occurrence++
if(occurrence % 2 == 0)
{
counter++
}
}
}
Why not just increment everytime and just divide by 2?
for(var i = 0; i<20; i++)
{
var j = i / 2; // or bit shift
//do work on j instead of i
}
I have the below code. I create a list (tried with array as well) with one million and one members. All of them has the value 0 by default. It should work like a multidimensional array, but it's not necessary as the first 'column' has to be numbers from 1-1.000.000. To make life easier I made 1.000.001 members to avoid using the 0th place.
At a certain point I have to use a member of this list addressed by a variable: list[n], and to avoid issues this only happens if n < 1.000.000. As there are members from 0-1.000.000 I think it's OK, but still my program crashes after a while with error code ArgumentOutOfRangeException.
What am I missing here?
int highestCount = 0;
int highestNum = 0;
List<int> list = new List<int>();
for(int j = 0; j <= 1000001; j++)
{
list.Add(0);
}
for (int i = 2; i < 1000000; i++)
{
int count = 0;
int number = i;
do
{
if (i % 2 == 0)
{
number = number / 2;
if (number < 1000000)
{
if (list[number] != 0)
{
count += list[number];
break;
}
else
{
count++;
}
}
else { count++; };
}
else
{
number = (number * 3) + 1;
if (number < 1000000)
{
if (list[number] != 0) //program dies here
{
count += list[number];
break;
}
else
{
count++;
}
}
else { count++; };
}
} while (number > 1);
list[i] = count;
if (count > highestCount)
{
highestCount = count;
highestNum = i;
}
}
MessageBox.Show(highestNum.ToString());
I think it's just a problem with your logic.
When i == 3 (on the second run), it will go into the do-while block.
Since i % 2 != 0 at that point, it will hit the else.
The number is multiplied by 3 and you add 1.
It is less than 1000000, but....
if(list[number] != 0)
never evaluates to true and you are stuck in an infinite do-while loop and it never breaks out because A) number will always be greater than 1 (satisfying the while condition); and B) you set every element of the array to zero in the code above this loop (thus never satisfying the above if condition):
for(int j = 0; j <= 1000001; j++)
{
list.Add(0);
}
I was trying out a code sample from this book that should demonstrate that the post decrement operator is not atomic. The code is as I have entered it into LinqPad.
void Main() {
var count = 0;
do {
_x = 10000;
for (int i = 0; i < 100; i++) {
new Thread(Go).Start();
}
Thread.Sleep(1000);
Console.WriteLine("Try "+ count);
count++;
} while (_x == 0);
Console.WriteLine(_x);
}
int _x = 10000;
void Go() { for (int i = 0; i < 100; i++) _x--; }
The idea is that decrementing _x in parallel on multiple threads without locking may lead to a value of _x other then 0 when all the threads have finished.
My problem is that no matter how long I seem to try I always get 0 as a result.
I have run the code on two different computers (both Windows 7) and two different versions of .NET and both give me the same result.
What am I missing here?
I have added 100000 interations in Go as Lasse V. Karlsen has suggested. The code now works as expected on the first try. I have also moved the Thread creation out of the loop and reduced the thread count as Henk Holterman has suggested.
void Main()
{
var count = 0;
do {
_x = 1000000;
var threads = Enumerable.Range(0,10).Select (_ => new Thread(Go)).ToList();
foreach (var t in threads)
{
t.Start();
}
Thread.Sleep(1000);
Console.WriteLine("Try "+ count);
count++;
} while (_x == 0);
Console.WriteLine(_x);
}
int _x;
void Go() { for (int i = 0; i < 100000; i++) _x--; }
The code now works as expected.