I can not recreate thread competing effect - c#

I read, in many many articles, that multiple threads will "compete" for the same resource and try to recreate it with the following code:
static void Main(string[] args)
{
List<int> list = new List<int>();
Thread t1 = new Thread(thread1);
t1.IsBackground = true;
t1.Start();
Thread t2 = new Thread(thread2);
t2.IsBackground = true;
t2.Start();
Thread.Sleep(3000);
foreach(int i in list)
{
Console.WriteLine(i);
}
Console.ReadLine();
void thread1()
{
for (int i = 0; i < 10000; i++)
{
list.Add(i);
}
}
void thread2()
{
for (int i = 10000; i < 20000; i++)
{
list.Add(i);
}
}
}
But the result is still very "nice and neat" in order (from 0 to 19999), what did I do wrong?

Related

C#, I want the main thread output the "num" after all sub-thread end, how to do so? Now I can only get '0' [duplicate]

This question already has answers here:
C# Waiting for multiple threads to finish
(5 answers)
Closed 2 years ago.
class Program
{
static void AddNumber1(ref int num)
{
num++;
}
static void AddNumber2(ref int num)
{
num++;
}
static void Main(string[] args)
{
//var mre = new ManualResetEvent(false);
int num = 0;
var th1 = new Thread(() =>
{
for (int i = 1; i <= 10; i++)
{
AddNumber1(ref num);
}
});
var th2 = new Thread(() =>
{
for (int i = 1; i <= 10; i++)
{
AddNumber1(ref num);
}
});
th1.Start();
th2.Start();
Console.WriteLine(num);
Console.Write("Press any key to end :");
Console.ReadKey(true);
}
You also could use Tasks instead of Threads like
var th1 = Task.Run(() =>
{
for (int i = 1; i <= 10; i++)
{
AddNumber1(ref num);
}
});
var th2 = Task.Run(() =>
{
for (int i = 1; i <= 10; i++)
{
AddNumber1(ref num);
}
});
Task.WaitAll(th1, th2);
Console.WriteLine(num);

How to get and print how many times a loop spins in a thread before it gets switched to other threads?

Instead of printing o and -, I want to print the number of o and - on the console. However, I have no idea how to get how many times a loop spins in a thread before it gets switched to other threads.
If there are events something likes OnLeaving and OnEntering on a thread, I can get the number of spins in the given time slice. Unfortunately, I have no such events.
class Program
{
public const int N = 1000;
static void Main(string[] args)
{
ThreadStart ts = DoWork;
Thread t = new Thread(ts);
t.Start();
for (int x = 0; x < N; x++)
{
Console.Write('o');
}
t.Join();
}
private static void DoWork()
{
for (int x = 0; x < N; x++)
{
Console.Write('-');
}
}
}
Could you show me how to do this scenario?
To reiterate: AbhayDixit's comment gives you a cycle counter. You just need to add a locking mechanism and reset the counters after a context switch.
I have modified your code to include a cycle counter. Note that I have increased N significantly. Otherwise, one thread will just run through its 1000 iterations at once - because you no longer have a Write() instruction to slow it down.
class Program
{
public const int N = 1000000;
private static object _l = new object();
private static int _i = 0;
private static int _j = 0;
static void Main(string[] args)
{
ThreadStart ts = DoWork;
Thread t = new Thread(ts);
t.Start();
for (int x = 0; x < N; x++)
{
lock (_l)
{
// j-thread has run?
if (_j > 0)
{
// print and reset j
Console.Write("j{0} ", _j);
_j = 0;
}
_i++;
}
}
t.Join();
// print remaining cycles
// one of the threads will have run after the other has finished and
// hence not been printed and reset.
if (_i > 0)
Console.Write("i{0} ", _i);
if (_j > 0)
Console.Write("j{0} ", _j);
Console.ReadKey();
}
private static void DoWork()
{
for (int x = 0; x < N; x++)
{
lock (_l)
{
// i-thread has run?
if (_i > 0)
{
// print and reset i
Console.Write("i{0} ", _i);
_i = 0;
}
_j++;
}
}
}
}

Iterating the assignment of a variable's name

So this is something I've always wondered..
Say I want 10 threads called t1 t2 t3 etc... But I don't want to write
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
Thread t3 = new Thread(run);
...
Rather something like this: (pseudo-code)
for(int i = 0; i <= 10; i++){
Thread t + i = new Thread(run);
}
Is there any way to do this?
Thanks in advance.
Edit: Okay, so this is basically what I wanted to do:
static void Main(string[] args)
{
int n = 0;
Program p = new Program();
List<Thread> threads = new List<Thread>();
for(int i = 0; i <= 10; i++)
{
threads.Add(new Thread(p.run));
}
foreach(Thread t in threads)
{
n++;
t.Name = "Thread " + n;
t.IsBackground = true;
t.Start();
}
Console.ReadKey(false);
}
Thanks all!
No, that's not possible. Why not just this?
for(int i = 0; i <= 10; i++){
new Thread(run);
}
If you really want to keep references to each thread, you can store them in a list.

Wait for threads to complete

private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 15; i++)
{
Thread nova = new Thread(Method);
nova.Start();
}
listBox1.Items.Add("Some text");
}
private void Method()
{
for (int i = 0; i < 15; i++)
{
Console.WriteLine(i);
}
}
This code does write: Some text and then numbers 111222333.....
I would like that it writes 111122223333.... and then on the end Some text.
is it possible to do that with threads (parent thread wait for child threads)? or do i have to use something else?
You need to keep track of all the threads, and use Thread.Join on each one. This waits until the specified thread terminates, and then continues executing. Like this:
var threads = new List<Thread>();
for (int i = 0; i < 15; i++)
{
Thread nova = new Thread(Method);
nova.Start();
threads.Add(nova);
}
foreach (var thread in threads)
thread.Join();
listBox1.Items.Add("Some text");
I suggest to use TPL to get this done. You won't need to spawn so many threads. By default TPL will use thread pool for that:
using System;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private const int TaskCount = 15;
static void Main(string[] args)
{
var tasks = new Task[TaskCount];
for (var index = 0; index < TaskCount; index++)
{
tasks[index] = Task.Factory.StartNew(Method);
}
Task.WaitAll(tasks);
Console.WriteLine("Some text");
}
private static void Method()
{
for (int i = 0; i < 15; i++)
{
Console.WriteLine(i);
}
}
}
}
You could have two threads, the 2nd one waiting on a signal to fire from the first.
private void Foo()
{
var signals = new List<ManualResetEvent>();
for (int i = 0; i < 15; i++)
{
var signal = new ManualResetEvent(false);
signals.Add(signal);
var thread = new Thread(() => { Method(); signal.Set(); });
thread.Start();
}
var completionTask = new Thread(() =>
{
WaitHandle.WaitAll(signals.ToArray());
CompletionWork();
});
completionTask.Start();
}
private void Method()
{
}
private void CompletionWork()
{
}
The better solution now with .Net 4.0 (and later) is to use Tasks, and invoke a method using ContinueWith
private void Foo()
{
var childThreads = new List<Task>();
for (int i = 0; i < 15; i++)
{
var task = new Task(Method);
task.Start();
childThreads.Add(task);
}
var completionTask = new Task(() =>
{
Task.WaitAll(childThreads.ToArray());
}).ContinueWith(t => CompletionWork());
}
private void Method()
{
}
private void CompletionWork()
{
}
The join answers also work, but require the containing thread to block. If you don't want the GUI to block, Spawn an additional thread around the 1st.
You can use thread.join to wait for threads to end. See http://www.dotnetperls.com/thread-join for an page on how to use it.

Wait until all threads finished their work in ThreadPool

i have this code:
var list = new List<int>();
for(int i=0;i<10;i++) list.Add(i);
for(int i=0;i<10;i++)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(x => {
Console.WriteLine(x);
}), list[i]);
}
And i want to know when all threadpools threads finished their work. How i can to do that?
You'll need to track this yourself.
One option for this is to use a counter and a reset event:
int toProcess = 10;
using(ManualResetEvent resetEvent = new ManualResetEvent(false))
{
var list = new List<int>();
for(int i=0;i<10;i++) list.Add(i);
for(int i=0;i<10;i++)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(x => {
Console.WriteLine(x);
// Safely decrement the counter
if (Interlocked.Decrement(ref toProcess)==0)
resetEvent.Set();
}),list[i]);
}
resetEvent.WaitOne();
}
// When the code reaches here, the 10 threads will be done
Console.WriteLine("Done");
In .NET Framework 4+ use the handy System.Threading.CountdownEvent class:
const int threadCount = 10;
var list = new List<int>(threadCount);
for (var i = 0; i < threadCount; i++) list.Add(i);
using (var countdownEvent = new CountdownEvent(threadCount))
{
for (var i = 0; i < threadCount; i++)
ThreadPool.QueueUserWorkItem(
x =>
{
Console.WriteLine(x);
countdownEvent.Signal();
}, list[i]);
countdownEvent.Wait();
}
Console.WriteLine("done");
I am not sure if ThreadPool exposes such functionality but you can use wait handles and by the way iterating twice seems unnecessary:
var events = new ManualResetEvent[10];
var list = new List<int>();
for (int i = 0; i < 10; i++)
{
list.Add(i);
events[i] = new ManualResetEvent(false);
int j = i;
ThreadPool.QueueUserWorkItem(x => {
Console.WriteLine(x);
events[j].Set();
}, list[i]);
}
WaitHandle.WaitAll(events);
This is how I would do it.
class Program
{
static void Main(string[] args)
{
var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
using (var countdown = new Countdown(items.Length))
{
foreach (var item in items)
{
ThreadPool.QueueUserWorkItem(o =>
{
Thread.SpinWait(100000000);
Console.WriteLine("Thread Done!");
countdown.Signal();
});
}
countdown.Wait();
}
Console.WriteLine("Job Done!");
Console.ReadKey();
}
public class Countdown : IDisposable
{
private readonly ManualResetEvent done;
private readonly int total;
private volatile int current;
public Countdown(int total)
{
this.total = total;
current = total;
done = new ManualResetEvent(false);
}
public void Signal()
{
lock (done)
{
if (current > 0 && --current == 0)
done.Set();
}
}
public void Wait()
{
done.WaitOne();
}
public void Dispose()
{
done.Dispose();
}
}
}
The thread pool does not tell you when the thread has finished executing, so the work item must do it itself. I changed the code like this:
var list = new List<int>();
ManualResetEvent[] handles = new ManualResetEvent[10];
for (int i = 0; i < 10; i++) {
list.Add(i);
handles[i] = new ManualResetEvent(false);
}
for (int i = 0; i < 10; i++) {
ThreadPool.QueueUserWorkItem(
new WaitCallback(x =>
{
Console.WriteLine(x);
handles[(int) x].Set();
}), list[i]);
}
WaitHandle.WaitAll(handles);
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(xyz));
}
bool working = true;
ThreadPool.GetMaxThreads(out int maxWorkerThreads, out int maxCompletionPortThreads);
while (working)
{
ThreadPool.GetAvailableThreads(out int workerThreads, out int completionPortThreads);
//Console.WriteLine($"{workerThreads} , {maxWorkerThreads}");
if (workerThreads == maxWorkerThreads)
{ working = false; }
}
//when all threads are completed then 'working' will be false
}
void xyz(object o)
{
console.writeline("");
}

Categories