Below is a simple example:
int Parallel_Count = int.Parse(nudParallelCount.Text);
for (int i = 1; i <= Parallel_Count; i++)
{
Thread string.Format("Thread_{0}", i) = new Thread(new ThreadStart(string.Format("Thread_{0}_Inside", i) ));
string.Format("Thread_{0}", i).Start();
}
As you see I did not use regular names for thread names and their entries and my codes have error because of them.
I want to add a counter (as a string) to thread names and thread entries names.
EDIT
One of my entries is like this :
public void Thread_1_Inside()
{
bloblobloblo -> i've created this expression by myself :)
}
You are looking for a container like an array or a list. Please make sure you understand those structures before you go into threading because they are pretty basic constructs and threading is tough stuff.
int Parallel_Count = int.Parse(nudParallelCount.Text);
Thread[] threads = new Thread[Parallel_Count];
for (int i = 0; i < Parallel_Count; i++)
{
threads[i] = new Thread(/*fill thread start here*/);
threads[i].Start();
}
Related
I want to create 10 threads with different names. Name should be a combination of name and id.ToString()
If I make a thread using Thread t = new Thread() then I know that I can do t.Name = name + id.ToString();, but if I there is some way to do it with the code example below I would love to know it.
string name = "Thread #";
int id = 0;
for (int i = 0; i < 10; i++)
{
new Thread(() =>
{
for (int j = 0; j <= 100; j++)
{
//Do something
}
}).Start();
}
you could do
var t = new Thread(...);
t.Name = "Thread " + i;
t.Start();
But you should probably use the thread pool instead of creating explicit threads. In this specific case where you have a loop, you should probably use a Parallel.For. In general when you want to run something on a background thread you should use Task.Run, or in some cases Dataflow. When using the task pool you should not name threads, since the threads may be reused for other things. See How can I assign a name to a task in TPL for similar concept for tasks.
Using the thread pool reduces the overhead for running things in the background, and usually also provides interfaces that are easier to use.
I just added Thread t = Thread.CurrentThread; and then I could do t.Name = $"Thread #{id}"; after.
This is what it looks like in its' entirety:
int tId = 0;
for (int i = 0; i < 10; i++)
{
new Thread(() =>
{
Thread t = Thread.CurrentThread;
tId++;
t.Name = $"Thread #{tId}";
Console.WriteLine($"{t.Name}");
}).Start();
I'm having a play with Threads to remind myself how they work, I haven't done any Threading code in ages.
So I thought I'd start with the most basic example, create n threads, get them updating a static int without a lock, so I can see it go wrong. However, it's working? The final value is 500 every time, it should be slightly random as Threads update the value at the same time
I know I'm doing something really stupid here but I can't see what
https://dotnetfiddle.net/w9TK5W
using System;
using System.Threading;
public class Program
{
public class Department
{
public static int a = 0;
public Department()
{
}
public void Inc()
{
a = a +5;
a = a -4;
}
}
public static void Main()
{
int count = 500;
Thread[] threads = new Thread[count];
Department dep = new Department();
for (int i = 0; i < count; i++)
{
Thread t = new Thread(new ThreadStart(dep.Inc));
threads[i] = t;
}
for (int i = 0; i < count; i++)
{
threads[i].Start();
}
Thread.Sleep(2000);
for (int i = 0; i < count; i++)
{
threads[i].Join();
}
Console.WriteLine(Department.a.ToString());
}
}
[Edit, more info]
So I changed the loop to look like this, it now works as expected
int b = a;
b = b+1;
int j=0;
for (int i=0; i<1E5; i++)
{
j += i;
}
a = b;
The computation in each thread is so short that probably each started thread is already ended before the next one actually starts.
This happens just by chance.
You should run in each thread a loop that performs millions of operations on a, and then you will probably detect the expected inconsistency.
The question has been edited with millions of operation which do not alter a, thus by chance again, the very few operations that actually alter a don't happen at the same time.
The question has been edited since the previous remark, but now it fails for a different reason than the expected initial one.
Reading a, waiting a bit, and altering a based on the read value is obviously not atomic.
If the loop simply performed a+=1, you could also see that this apparently trivial operation is not atomic either.
Old title: Is an array of lists thread safe in C#?
I try to use a pool of lists for parallel processing. I create lists in an array and then use a ConcurrentBag of integers to allocate them to threads. Since the entire code is quite long I made an excerpt. In the below example each thread would need 5 lists of object x.
int maxThreads = 64;
ConcurrentBag<int> pool = new ConcurrentBag<int>();
// Populate ConcurrentBag with values 0 through 63
for (int i = 0; i <= maxThreads - 1; i++)
{
pool.Add(i);
}
List<x>[,] ABCList = new List<x>[maxThreads, 5];
Parallel.ForEach(zList,
new ParallelOptions { MaxDegreeOfParallelism = maxThreads },
p =>
{
while (!pool.TryTake(out slot));
// Do something here with ABCList[slot, 1....5]
// Example: ABCList[slot, 1].[1].Field1 = 2;
// Example: ABCList[slot, 1].[1].Field2 = "abc";
pool.Add(slot);
});
So this runs without an error or any warnings. However inside parallel processing it sometimes fails to update values in ABCList[slot, 1....5]. By sometimes I mean 2-5 cases out of 1000. When I check in debug mode I can't reproduce the symptom. When I press F11 the list values are updated.
Please consider that I'm a hobby programmer and I may do something obviously wrong here. Any ideas how to do this correctly?
EDIT
Based on the suggestion of Peter I rewrote like this:
int maxThreads = 64;
ConcurrentBag<int> pool = new ConcurrentBag<int>();
ConcurrentDictionary <int, List<x>[]> ABCList = new ConcurrentDictionary<int, List<x>[]>();
// Initialize ConcurrentDictionary
for (int i = 0; i < maxThreads; i++)
{
pool.Add(i);
ABCList[i] = new List<x>[5];
for (int w = 0; w <= 4; w++)
{
ABCList[i][w] = templateABCList[w].ConvertAll(p => p);
}
}
Parallel.ForEach(zList,
new ParallelOptions { MaxDegreeOfParallelism = maxThreads },
p =>
{
while (!pool.TryTake(out slot));
// Do something here with ABCList[slot][1...5]
// Example: ABCList[slot][1][1].Field1 = 2;
// Example: ABCList[slot][1][1].Field2 = "abc";
pool.Add(slot);
});
The problem still exists. The list fails to update in some cases. What do I do wrong?
You can Use System.Collections.Concurrent Name Space for Thread Safe Collections,
and you can Use ConcurrentBag Class to Create Object(List) Pool
if you want Any list in pool is Thread safe , you can Use
var threadSafeArrayList = ArrayList.Synchronized(new ArrayList());
For Create each List Object
I have difficulty understanding why the multithreading fails to update values before the thread completes. Does the separate thread have its own copy of the references or values?
If not, to my understanding the code below should work properly when MyMethod is called, but often it does not create instances of some MyType objects in the array before the thread.IsAlive becomes false:
class MyClass
{
static MyType[] obj = new MyType[Environment.ProcessorCount - 1];
void MyMethod()
{
Thread[] threads = new Thread[Environment.ProcessorCount - 1];
for (int i = 0; i < Environment.ProcessorCount - 1; i++)
{
threads[i] = new Thread(() => FillObjects(i));
threads[i].Priority = ThreadPriority.AboveNormal;
threads[i].Start();
}
while (threads[i].Any(c => c.IsAlive))
{
Thread.Sleep(50);
}
}
void FillObjects(int i)
{
obj[i] = new MyType();
//perform actions with obj[i] to fill it with necessary values
}
}
You need to assign the value of the loop variable to a local variable. Otherwise it's possible that the first execution of FillObjects(i) is executed after i was incremented so FillObjects(0) is never called and therefore obj[0] is never assigned.
void MyMethod()
{
Thread[] threads = new Thread[Environment.ProcessorCount - 1];
for (int i = 0; i < Environment.ProcessorCount - 1; i++)
{
int local = i;
threads[i] = new Thread(() => FillObjects(local));
threads[i].Priority = ThreadPriority.AboveNormal;
threads[i].Start();
}
while (threads.Any(c => c.IsAlive))
{
Thread.Sleep(50);
}
}
On a multi processor machine (which you must have) results written to a memory location in one thread may not be visible in another thread due to caching. Use Thread.VolatileRead and Thread.VolatileWrite read in order to read and write "through" the cache.
Cf. the chapter on threading in c# 3.0 in a Nutshell for an explanation. (Look for the question "Is it possible for the Wait method to write "False"?". That example is basically your case.)
Hi all i am trying to write and anonymous delegate. as the integer variable is shared among the delegate i need it to be the local instance of every delegate such that rs[0] always gets nics[0], rs[1] always gets nics[1] and so on... how will i achieve this.
for (int i = 0; i < nics.Count; i++)
{
rs[i] = new RollingSeries(monitor, new RollingSeries.NextValueDelegate(delegate()
{
return GetNetworkUtilization(nics[i]);
}));
}
Abdul khaliq
Make a local copy of i:
for (int i = 0; i < nics.Count; i++)
{
int j = i;
rs[i] = new RollingSeries(monitor, new RollingSeries.NextValueDelegate(delegate()
{
return GetNetworkUtilization(nics[j]);
}));
}
The Beauty of Closures
Use a local to get a different value per iteration
for (int i = 0; i < nics.Count; i++)
{
int localI = i;
rs[i] = new RollingSeries(monitor, new RollingSeries.NextValueDelegate(delegate()
{
return GetNetworkUtilization(nics[localI]);
}));
}
Put int j = i inside your loop and refer to j within the lambda expression.
If you are curious about why this happens, here is an MSDN blog entry containing a detailed technical explanation: Closing over the loop variable considered harmful