This question already has answers here:
increment a count value outside parallel.foreach scope
(4 answers)
Closed 9 years ago.
I have a trouble with getting perfect result using Parallel.
What I did
protected void Page_Load(object sender, EventArgs e)
{
List<int> listInt = new List<int>();
for (int i = 0; i < 10000; i++)
{
listInt.Add(i);
}
int cnt = 0;
Parallel.ForEach(listInt, num =>
{
cnt++;
}
);
System.Threading.Thread.Sleep(0);
//it should show 10000 but it gives random result
Response.Write(cnt);
}
I was expecting to get 10000 as response but it is giving random result.
What I am doing wrong to get the accurate result.
Live test is here.
Thank you so much.
Your code is not threadsafe.
You can use something like this:
private static readonly object SyncRoot = new object();
and
lock (SyncRoot)
{
cnt++;
}
Check this dotnetfiddle http://dotnetfiddle.net/D7QoP9
Your code is not "threadsafe", that is a "Race".
Add a lock around cnt++ to see the expected result.
Or just use
Interlocked.Increment(ref cnt);
Related
This question already has answers here:
List Index Out of Range exception when creating a task
(3 answers)
Closed 3 years ago.
I'm trying to figure out why is this error showing, but I can't. I think that everything's okay, but at some point the value "i" at readTest is == 2. Which is not supposed to... listW has 2 objects, and the "i" should only be 0 and 1. I don't where the 2 is coming from. Am I making anything wrong? I've done some testing and the i=2 only happens at readTest. What's happening?
Thank you for your attention guys
public void readTest(int i)
{
for (int j = 0; j != leftListList[i].getKeyValues().Length; j++)
{
string read = ws.Read(listW[i], wi[i].GetKey(), leftListList[i].getKeyValues()[j]);
WsRead wsRead = wi[i].BuildRead(read, leftListList[i].getKeyValues()[j]);
readList.Add(wsRead);
Console.WriteLine("READ: " + leftListList[i].getKeyValues()[j]);
}
}
public void threadTest()
{
for (int i = 0; i != listW.Length; i++)
{
Thread t = new Thread(() => readTest(i));
t.Start();
}
}
Introduce a local variable, say index:
for (int i = 0; i < listW.Length; i++) // i < listW.Length is more readable
{
int index = i;
...
else
{
// now each thread has its own index
Thread t = new Thread(() => readTest(index));
t.Start();
}
}
when Thread finally starts (it takes time to create a new thread), the loop is completed and thus i == 2
This question already has answers here:
What's the fastest way to read a text file line-by-line?
(9 answers)
Closed 5 years ago.
So I am just starting out C# with little to no knowledge, so this is more for learning for me than practical use. Therefore what I really would like to know is how I can get my code to work my way, even if there is a much simpler/quicker/smarter solution.
So what I wanna do is create a string array, and using a loop read in each line from a text file into a corresponding element of the array. That's what I tried to do here, and I would love to hear what solutions you have for this.
{
class Program
{
static void Main(string[] args)
{
StreamReader ki = new StreamReader("kiserlet.txt");
string[] a = new string[15];
Console.ReadLine();
int y = 0;
int n = 0;
for (int i = 0; i > 15; i++)
{
a[n] = Convert.ToString(ki.ReadLine());
n++;
}
for (int x = 0;x > 15;x++)
{
Console.WriteLine(a[y]);
y++;
}
Console.ReadLine();
ki.Close();
}
}
}
You can read each line of the file into an array, then iterate through it.
class Program
{
static void Main(string[] args)
{
// this will read all lines from within the File
// and automatically put them into an array
//
var linesRead = File.ReadLines("kiserlet.txt");
// iterate through each element within the array and
// print it out
//
foreach (var lineRead in linesRead)
{
Console.WriteLine(lineRead);
}
}
}
This question already has answers here:
Starting a new thread in a foreach loop
(5 answers)
Closed 5 years ago.
I am trying to learn C# multithreading. This question might be stupid for some but anyways I will still ask it.
Question:
I'm trying to figure out where should I put (if I'm asking the right question)
the thread.wait() method. So it could show all the child threads in the console. This is the output that I would like to have.
The int num that I inputted is 3.
This should be the output (I am running this with breakpoint):
This is the current output:
Here is my Code:
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Input number of threads: ");
int num = Convert.ToInt32(Console.ReadLine());
Task[] TaskArray = new Task[num];
for (int i = 0; i <= num-1; i++)
{
TaskArray[i] = Task.Run(() => { DifferentMethod(i); });
}
for (int i = 0; i <= num - 1; i++)
{
TaskArray[i].Wait();
}
}
static void DifferentMethod(object ThreadID)
{
while (true)
{
Console.WriteLine("{0} is Running",ThreadID);
Thread.Sleep(500);
}
}
}
}
This has nothing to do with your waiting part.
You need to make a local copy of your variable:
for (int i = 0; i <= num-1; i++)
{
int localCopy = i;
TaskArray[i] = Task.Run(() => { DifferentMethod(localCopy); });
}
Because your i is "captured" (for lack of a better word) but it has already changed by then. So you make a local copy so the capture is on the local copy, that never changes.
You could use the static method from the Task class Task.WaitAll(TaskArray) and the main thread will wait at that point for all tasks to finish
This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 6 years ago.
I am learning about multithreading in C#. It is making me hard, so I am doing some simple programs to understand it better.
I realized that if I have:
static void Main()
{
Task[] tasks = new Task[4];
for (int i = 0; i < 4; i++)
{
tasks[i] = Task.Factory.StartNew(() => {
Console.WriteLine(i);
});
}
Console.ReadKey();
}
The output is 4444, no 0123 like I expected.
Why is it?
EDIT:
Sadiq said in his answer that the reason of this behaviour is because i'm closing over a loop variable. But if I add to my code Thread.sleep(500); outside the lambda statement and inside the loop, I get 0123.
So, why this behaviour supposedly caused by clousures don't occurs with adding this line of code?
it seems to me that the reason of the asked behaviour is other. The code for if you don't understand what I've just written:
static void Main()
{
Task[] tasks = new Task[4];
for (int i = 0; i < 4; i++)
{
tasks[i] = Task.Factory.StartNew(() => {
Console.WriteLine(i);
});
Thread.Sleep(500);
}
//Now the output is: 0123
Console.ReadKey();
}
Make a local variable - copy the value into it and you should get the expected output:
static void Main()
{
Task[] tasks = new Task[4];
for (int i = 0; i < 4; i++)
{
int x = i;
tasks[x] = Task.Factory.StartNew(() => {
Console.WriteLine(x);
});
}
Console.ReadKey();
}
The reason you get the unexpected output is because i gets shared. You are closing over a loop variable.
This question already has an answer here:
Detailed Explanation of Variable Capture in Closures
(1 answer)
Closed 8 years ago.
I expect the variable in the loop to output 1,2,3 to my listbox below. But it outputs
2
2
2
what is wrong?
C# Code
public partial class Tester : Form
{
public int test = 1;
............................
private void button1_Click(object sender, EventArgs e)
{
test++;
for (int i = 0; i < 3; i++)
{
Task t = Task.Factory.StartNew(() =>
{
System.Threading.Thread.Sleep(5000);
}).ContinueWith(o =>
{
listBox1.Items.Add(test);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
If you want to know the sequence in which the Tasks are done you can use the following:
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 3; i++)
{
int tasknumber = test;
Task t = Task.Factory.StartNew(() =>
{
System.Threading.Thread.Sleep(5000);
return tasknumber;
}).ContinueWith(o =>
{
listBox1.Items.Add(o.Result);
}, TaskScheduler.FromCurrentSynchronizationContext());
test++;
}
}
With this code, the value of test is increased at the end of every loop. In the first Task, the tasknumber will be 1. In the second Task the tasknumber will be 2 etc. When the Task is done, the result will be passed to your ListBox.
You might also want to read this blog about StartNew.