Is there a simple way to check if any threads are waiting for a specific ManualResetEvent
object to be set? It seems to me that the computer must be somehow keeping a queue of the
paused threads to restore later, so I'm just hoping to do the obvious and access
this list (just to check whether or not it is empty)...but I couldn't find a
method from looking at Microsoft's related Threading/WaitHandle/Monitor help pages.
Test code is below. I'd simply like to replace the uglyWaiters counter.
using System;
using System.Threading;
namespace demo
{
class Program
{
static void Main()
{
var gate = new ManualResetEvent(false);
int uglyWaiters = 0; // I want to stop using this variable and instead use something built into ManualResetEvent
new Thread(() =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("a" + i);
uglyWaiters++;
gate.WaitOne();
uglyWaiters--;
Thread.Sleep(400);
}
}).Start();
new Thread(() =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("b" + i);
uglyWaiters++;
gate.WaitOne();
uglyWaiters--;
Thread.Sleep(500);
}
}).Start();
for (int count = 0; count < 15; count++)
{
Console.WriteLine(uglyWaiters + " threads waiting at t=" + count*230 + "ms");
gate.Set(); Thread.Sleep(30); gate.Reset();
Thread.Sleep(200);
}
Console.ReadLine();
}
}
}
Related
This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 4 years ago.
First off, I'm new to C#, and this is the first program I've written that uses threads. Sorry if it's a bit basic.
Here's my app:
class Program
{
static void AddNumbers()
{
int count = 0;
for (int counter = 0; counter < 90000000; counter++)
{
count += counter;
}
}
static void Main()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 50; i++)
{
// Non-threaded
//AddNumbers();
//Console.WriteLine((i + 1).ToString());
// Threaded
new Thread(() =>
{
//Thread.CurrentThread.IsBackground = true;
AddNumbers();
Thread.Sleep(1000);
Console.WriteLine((i + 1).ToString());
}).Start();
}
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0:hh\\:mm\\:ss}", stopwatch.Elapsed);
Console.ReadLine();
}
}
It simply loops i times and adds a bunch of numbers each time. When I run the AddNumbers() version non-multithreaded, it correctly displays 1, 2, 3... etc, but when I run it multithreaded, it returns the same indexes 2-3 times, skips some, and returns the stopwatch value before all the threads have executed.
Can someone please help spot where my error is and most of all clarify my thinking about how threads work in C#? Thanks!
When I run the AddNumbers() version non-multithreaded, it correctly displays 1, 2, 3... etc, but when I run it multithreaded, it returns the same indexes 2-3 times, skips some
It happens, because i is captured, but changed in outside loop.
Read more about it here:
Captured variable in a loop in C#
http://www.trycatchthat.com/csharp/fundamentals/2016/02/29/csharp-closure-loops.html
In order to make it work properly you need to save a local copy:
for (int i = 0; i < 50; i++)
{
// Non-threaded
//AddNumbers();
//Console.WriteLine((i + 1).ToString());
// Threaded
int iCopy = i;
new Thread(() =>
{
//Thread.CurrentThread.IsBackground = true;
AddNumbers();
Thread.Sleep(1000);
Console.WriteLine((iCopy + 1).ToString());
}).Start();
}
returns the stopwatch value before all the threads have executed
It happens, because you actually never join your threads and wait for them to execute.
It can be achieved by storing all threads and calling thread.Join():
Thread[] threads = new Thread[50];
for (int i = 0; i < 50; i++)
{
// Non-threaded
//AddNumbers();
//Console.WriteLine((i + 1).ToString());
// Threaded
int iCopy = i;
threads[i] = new Thread(() =>
{
//Thread.CurrentThread.IsBackground = true;
AddNumbers();
Thread.Sleep(1000);
Console.WriteLine((iCopy + 1).ToString());
});
thread[i].Start();
}
for (int i = 0; i < 50; i++)
threads[i].Join();
Read more about waiting for threads to complete here:
Create multiple threads and wait all of them to complete
This is how people used to do it before TPL has been invented.
Now, general rule is not to use Thread, but use Task or Parallel instead.
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Task[] tasks = new Task[50];
for (int i = 0; i < 50; i++)
{
int iCopy = i;
tasks[i] = Task.Run(() => {
AddNumbers();
Thread.Sleep(1000);
Console.WriteLine((iCopy + 1).ToString());
});
}
Task.WaitAll(tasks);
As far as I know, the variable in thread should be not safe if not locked. But I tried it on Unity, and found it different.
I try the code below:
void Awake () {
Thread thread = new Thread(new ThreadStart (demo));
thread.Start ();
for (int i = 0; i < 5000; i++) {
count = count + 1;
}
}
void demo() {
for (int i = 0; i < 5000; i++) {
count = count + 1;
}
}
And I try to Debug.Log(count), and every times I try it that is 10000. But it should be a number which is less than 10000 because of not thread safety, shouldn't it? So can anyone tell me why?
Here's an Minimal, Complete, and Verifiable example of your code:
void Main()
{
Awake();
Console.WriteLine(count);
}
private int count = 0;
public void Awake()
{
Thread thread = new Thread(new ThreadStart(demo));
thread.Start();
for (int i = 0; i < 5000; i++)
{
count = count + 1;
}
thread.Join();
}
public void demo()
{
for (int i = 0; i < 5000; i++)
{
count = count + 1;
}
}
If you run that you get 10000 out. This is because by the time the thread has started the .Awake() method has finished its loop and thus no conflict occurs.
Try changing the loops to for (int i = 0; i < 50000; i++) then the result I got for one run is 89922. It changes each time, but sometimes I still get 100000.
The thread need some time to schedule to start. The main thread might finish the increments before the other thread start. Try to use a large value like 50000000.
I am trying to optimize a search algorithm I am using to find marked Symbols in TwinCat 3 through the ADS Interface. The question is not TwinCat related so don't get scared off yet.
The problems:
Symbols are not loaded at once. I think the TwinCatAds library use lazy loading.
Symbols have treelike structure of non-binary not balanced tree.
The solution:
You can open more than one stream to ADS. And handle the the streams in multiple threads.
The question is, I divide the first level of symbols by the number of the processor cores. So Because the tree is unbalanced some of the Threads finish faster than the others. Because of this I need a nicer solution how to divide the work between the threads.
PS: I can't use the Parallel.ForEach(). Because of the streams it results in the same or greater time amount as the single thread solution.
My test code looks looks this, it just counts all Symbols of a huge Project.
using TwinCAT.Ads;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Collections;
namespace MultipleStreamsTest
{
class Program
{
static int numberOfThreads = Environment.ProcessorCount;
static TcAdsClient client;
static TcAdsSymbolInfoLoader symbolLoader;
static TcAdsSymbolInfoCollection[] collection = new TcAdsSymbolInfoCollection[numberOfThreads];
static int[] portionResult = new int[numberOfThreads];
static int[] portionStart = new int[numberOfThreads];
static int[] portionStop = new int[numberOfThreads];
static void Connect()
{
client = new TcAdsClient();
client.Connect(851);
Console.WriteLine("Conected ");
}
static void Main(string[] args)
{
Connect();
symbolLoader = client.CreateSymbolInfoLoader();
CountAllOneThread();
CountWithMultipleThreads();
Console.ReadKey();
}
static public void CountAllOneThread()
{
Stopwatch stopwatch = new Stopwatch();
int index = 0;
stopwatch.Start();
Console.WriteLine("Counting with one thread...");
//Count all symbols
foreach (TcAdsSymbolInfo symbol in symbolLoader)
{
index++;
}
stopwatch.Stop();
//Output
Console.WriteLine("Counted with one thred " + index + " symbols in " + stopwatch.Elapsed);
}
static public int countRecursive(TcAdsSymbolInfo symbol)
{
int i = 0;
TcAdsSymbolInfo subSymbol = symbol.FirstSubSymbol;
while (subSymbol != null)
{
i = i + countRecursive(subSymbol);
subSymbol = subSymbol.NextSymbol;
i++;
}
return i;
}
static public void countRecursiveMultiThread(object portionNum)
{
int portionNumAsInt = (int)portionNum;
for (int i = portionStart[portionNumAsInt]; i <= portionStop[portionNumAsInt]; i++)
{
portionResult[portionNumAsInt] += countRecursive(collection[portionNumAsInt][i]);//Collection Teil
}
}
static public void CountWithMultipleThreads()
{
Stopwatch stopwatch = new Stopwatch();
int sum = 0;
stopwatch.Start();
Console.WriteLine("Counting with multiple thread...");
for (int i = 0; i < numberOfThreads; i++)
{
collection[i] = symbolLoader.GetSymbols(true);
}
int size = (int)(collection[0].Count / numberOfThreads);
int rest = collection[0].Count % numberOfThreads;
int m = 0;
for (; m < numberOfThreads; m++)
{
portionStart[m] = m * size;
portionStop[m] = portionStart[m] + size - 1;
}
portionStop[m - 1] += rest;
Thread[] threads = new Thread[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++)
{
threads[i] = new Thread(countRecursiveMultiThread);
threads[i].Start(i);
Console.WriteLine("Thread #" + threads[i].ManagedThreadId + " started, fieldIndex: " + i);
}
//Check when threads finishing:
int threadsFinished = 0;
bool[] threadFinished = new bool[numberOfThreads];
int x = 0;
while (true)
{
if (threads[x].Join(10) && !threadFinished[x] )
{
Console.WriteLine("Thread #" + threads[x].ManagedThreadId + " finished ~ at: " + stopwatch.Elapsed);
threadsFinished++;
threadFinished[x] = true;
}
x++;
x = x % numberOfThreads;
if (threadsFinished == numberOfThreads) break;
Thread.Sleep(50);
}
foreach (int n in portionResult)
{
sum += n;
}
sum += collection[0].Count;
stopwatch.Stop();
//Output
Console.WriteLine("Counted with multiple threds in Collection " + sum + " symbols " + " in " + stopwatch.Elapsed);
for (int i = 0; i < numberOfThreads; i++)
{
Console.WriteLine("#" + i + ": " + portionResult[i]);
}
}
}
}
The console output:
If you trying to run the Code use TwinCat.Ads Version 4.0.17.0(that i am using). They broke something in the new version that is available with NuGet.
Make a thread pool and keep track of threads running and idling status. At each branch check if there is idling threads, if there is assign thread to sub branch.
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++;
}
}
}
}
I was trying to spawn certain number of threads. But when I pass arguments to the function the output is random. It chooses some values of variable 'i' for multiple times and ignores some. I am a newbie in C#. Please explain if I am doing anything wrong.
using System;
using System.Threading;
public class first
{
public static void tone(int i)
{
Console.WriteLine("Hi ! this is thread : {0} ",i);
Thread.Sleep(10);
}
public static void Main(String[] args)
{
int i;
for (i = 0; i < 10; i++)
{
Thread th1 = new Thread(()=>tone(i) );
th1.Start();
// Console.WriteLine(i);
}
Console.WriteLine("hey there!");
Console.ReadLine();
}
}
Because of closure:
Change your code to:
int i;
for (i = 0; i < 10; i++)
{
int j = i;
Thread th1 = new Thread(()=>tone(j) );
th1.Start();
// Console.WriteLine(i);
}