Μeasuring the time of a thread quantum [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 months ago.
Improve this question
I'm trying to measure the time each thread quantum takes using c#.
using System;
using System.Diagnostics;
using System.Threading;
using System.Collections.Concurrent;
namespace pr
{
public static class Program
{
private static Stopwatch watch = new Stopwatch();
private static long t = 0;
private static volatile int id = 0;
private static BlockingCollection<long> deltas = new();
public static void Main(string[] args)
{
ProcessAffinity();
PriorityClass();
ThreadDemo();
}
private static void ProcessAffinity()
{
Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)(1 << 0);
}
private static void PriorityClass()
{
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;
}
private static void ThreadDemo()
{
var thread1 = new Thread(() => InsideThread())
{
IsBackground = true,
Priority = ThreadPriority.Highest
};
var thread2 = new Thread(() => InsideThread())
{
IsBackground = true,
Priority = ThreadPriority.Highest
};
watch.Start();
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
var avg = deltas.Average();
Console.WriteLine("Average: " + avg);
foreach (var e in deltas)
{
Console.WriteLine("delta: " + e);
}
}
private static void InsideThread()
{
while (true)
{
var currentId = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("id" + currentId);
if (id == 0)
{
id = currentId;
}
if (id != currentId)
{
var newt = watch.ElapsedMilliseconds;
deltas.Add(newt - t);
t = newt;
id = currentId;
}
if (watch.ElapsedMilliseconds > 3000) break;
}
}
}
}
If I print the id of the current thread to the console, everything kind of works and the delta gets counted. But the Console.WriteLine changes the context (I guess? I'm new in this topic) and increases the time, so the result is not correct (it's around 100 ms, while it's supposed to be around 32 ms). However, if I comment the Console.WriteLine("id" + currentId); out, the threads don't change: thread2 seems to start only after thread1 completes its work, so the final delta is 3000ms + something. Increasing the time doesn't help too. My question is: why don't the threads run simultaneously when Console.WriteLine() is commented out? How to measure the time of a thread quantum correctly? Should I use any locks? (I've tried, but nothing changed)

My guess is that Console.WriteLine will yield the time slice, possibly due to blocking on a lock. This is not really unexpected.
Without yielding, the thread1 will have a higher priority than your "main" thread. So it is likely that thread2.Start(); will never be run before the thread1 has completed.
To get around this you could use a manualResetEvent. Let each thread wait on the same event, and set this from the main thread after both have been started. Waiting on the event will block the threads, letting the main thread run. When the event has been set, both threads should be eligible to run.
Note that I'm not at all sure that this will give any accurate results, but it should fix the current behavior you are seeing.

Related

I am trying to call a method in a loop .It should be called only 20 times in 10 seconds . I am using semaphore like the below code

By using the below code firstly some of the calls are not getting made lets say out of 250 , 238 calls are made and rest doesn't.Secondly I am not sure if the calls are made at the rate of 20 calls per 10 seconds.
public List<ShowData> GetAllShowAndTheirCast()
{
ShowResponse allShows = GetAllShows();
ShowCasts showCast = new ShowCasts();
showCast.showCastList = new List<ShowData>();
using (Semaphore pool = new Semaphore(20, 20))
{
for (int i = 0; i < allShows.Shows.Length; i++)
{
pool.WaitOne();
Thread t = new Thread(new ParameterizedThreadStart((taskId) =>
{
showCast.showCastList.Add(MapResponse(allShows.Shows[i]));
}));
pool.Release();
t.Start(i);
}
}
//for (int i = 0; i < allShows.Shows.Length; i++)
//{
// showCast.showCastList.Add(MapResponse(allShows.Shows[i]));
//}
return showCast.showCastList;
}
public ShowData MapResponse(Show s)
{
CastResponse castres = new CastResponse();
castres.CastlistResponse = (GetShowCast(s.id)).CastlistResponse;
ShowData sd = new ShowData();
sd.id = s.id;
sd.name = s.name;
if (castres.CastlistResponse != null && castres.CastlistResponse.Any())
{
sd.cast = new List<CastData>();
foreach (var item in castres.CastlistResponse)
{
CastData cd = new CastData();
cd.birthday = item.person.birthday;
cd.id = item.person.id;
cd.name = item.person.name;
sd.cast.Add(cd);
}
}
return sd;
}
public ShowResponse GetAllShows()
{
ShowResponse response = new ShowResponse();
string showUrl = ClientAPIUtils.apiUrl + "shows";
response.Shows = JsonConvert.DeserializeObject<Show[]>(ClientAPIUtils.GetDataFromUrl(showUrl));
return response;
}
public CastResponse GetShowCast(int showid)
{
CastResponse res = new CastResponse();
string castUrl = ClientAPIUtils.apiUrl + "shows/" + showid + "/cast";
res.CastlistResponse = JsonConvert.DeserializeObject<List<Cast>>(ClientAPIUtils.GetDataFromUrl(castUrl));
return res;
}
All the Calls should be made , but I am not sure where they are getting aborted and even please let me know how to check the rate of calls being made.
I'm assuming that your goal is to process all data about shows but no more than 20 at once.
For that kind of task you should probably use ThreadPool and limit maximum number of concurrent threads using SetMaxThreads.
https://learn.microsoft.com/en-us/dotnet/api/system.threading.threadpool?view=netframework-4.7.2
You have to make sure that collection that you are using to store your results is thread-safe.
showCast.showCastList = new List<ShowData>();
I don't think that standard List is thread-safe. Thread-safe collection is ConcurrentBag (there are others as well). You can make standard list thread-safe but it requires more code. After you are done processing and need to have results in list or array you can convert collection to desired type.
https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentbag-1?view=netframework-4.7.2
Now to usage of semaphore. What your semaphore is doing is ensuring that maximum 20 threads can be created at once. Assuming that this loop runs in your app main thread your semaphore has no purpose. To make it work you need to release semaphore once thread is completed; but you are calling thread Start() after calling Release(). That results in thread being executed outside "critical area".
using (Semaphore pool = new Semaphore(20, 20)) {
for (int i = 0; i < allShows.Shows.Length; i++) {
pool.WaitOne();
Thread t = new Thread(new ParameterizedThreadStart((taskId) =>
{
showCast.showCastList.Add(MapResponse(allShows.Shows[i]));
pool.Release();
}));
t.Start(i);
}
}
I did not test this solution; additional problems might arise.
Another issue with this program is that it does not wait for all threads to complete. Once all threads are started; program will end. It is possible (and in your case I'm sure) that not all threads completed its operation; this is why ~240 data packets are done when program finishes.
thread.Join();
But if called right after Start() it will stop main thread until it is completed so to keep program concurrent you need to create a list of threads and Join() them at the end of program. It is not the best solution. How to wait on all threads that program can add to ThreadPool
Wait until all threads finished their work in ThreadPool
As final note you cannot access loop counter like that. Final value of loop counter is evaluated later and with test I ran; code has tendency to process odd records twice and skip even. This is happening because loop increases counter before previous thread is executed and causes to access elements outside bounds of array.
Possible solution to that is to create method that will create thread. Having it in separate method will evaluate allShows.Shows[i] to show before next loop pass.
public void CreateAndStartThread(Show show, Semaphore pool, ShowCasts showCast)
{
pool.WaitOne();
Thread t = new Thread(new ParameterizedThreadStart((s) => {
showCast.showCastList.Add(MapResponse((Show)s));
pool.Release();
}));
t.Start(show);
}
Concurrent programming is tricky and I would highly recommend to do some exercises with examples on common pitfalls. Books on C# programming are sure to have a chapter or two on the topic. There are plenty of online courses and tutorials on this topic to learn from.
Edit:
Working solution. Still might have some issues.
public ShowCasts GetAllShowAndTheirCast()
{
ShowResponse allShows = GetAllShows();
ConcurrentBag<ShowData> result = new ConcurrentBag<ShowData>();
using (var countdownEvent = new CountdownEvent(allShows.Shows.Length))
{
using (Semaphore pool = new Semaphore(20, 20))
{
for (int i = 0; i < allShows.Shows.Length; i++)
{
CreateAndStartThread(allShows.Shows[i], pool, result, countdownEvent);
}
countdownEvent.Wait();
}
}
return new ShowCasts() { showCastList = result.ToList() };
}
public void CreateAndStartThread(Show show, Semaphore pool, ConcurrentBag<ShowData> result, CountdownEvent countdownEvent)
{
pool.WaitOne();
Thread t = new Thread(new ParameterizedThreadStart((s) =>
{
result.Add(MapResponse((Show)s));
pool.Release();
countdownEvent.Signal();
}));
t.Start(show);
}

Having a Server progress two threads at the same time

I have two threads reaching a point in the server program at slightly differing times, both sending a string. I want the server to pause at this point until both threads have received a string and then continue. Currently I am using Console.ReadKey(); in order to "pause" the thread. But this isn't a solution as I need to press a key twice (one for each thread) in order to progress.
Is there a possibility of having a global counter in the program class which is accessible and editable by all threads at all times? A similiar concept to a ConcurrentDictionary. That way I can distinguish between threads based on which thread sent a string first and make the program hang until the counter is satisfied that both clients have 'answered'.
class Program
{
public static bool isFirstThread = false;
static void Main(string[] args)
{
runServer();
}
static void runServer()
{
//server setup
Thread[] threadsArray = new Thread[2];
int i = 0;
try
{
while(true) //game loop
{
Socket connection;
connection = listener.AcceptSocket();
threadRequest = new Handler();
if(i==0) //first thread
{
threadsArray[i] = new Thread(() => threadRequest.clientInteraction(connection, true);
}
else //not first thread
{
threadsArray[i] = new Thread(() => threadRequest.clientInteraction(connection, false);
}
threadsArray[i].Start();
i++;
}
}
catch(Exception e)
{
Console.WriteLine("Exception: " + e.ToString());
}
}
}
class Handler
{
public void clientInteraction(Socket connection, bool isFirstThread)
{
string pAnswer = string.Empty;
//setup streamReaders and streamWriters
while(true) //infinite game loop
{
//read in a question and send to both threads.
pAnswer = sr.ReadLine();
Console.WriteLine(pAnswer);
Console.ReadKey(); //This is where I need the program to hang
awardPoints();
}
}
}
This is a rough idea of what my code is doing, I've chopped quite a bit to avoid question bloat so there might be a couple of things that are in error that I've missed.
I could in theory just set a timer from when the question string is sent from the server, but I would rather not at this stage.
Any thoughts or pointers would be much appreciated. Thanks in advance.
Use a System.Threading.Barrier, which is designed for this exact purpose: making each thread in a group of threads wait until all of them have reached some point in their computation. Initialize it in runServer() like this:
Barrier barrier = new Barrier(2);
And do this at the end of each thread:
barrier.SignalAndWait();

Thread Pool with BlockingCollection

Problem: There are multiple threads accessing a resource. I need to limit their number to a constant MaxThreads. Threads who cannot enter the thread pool should get an error message.
Solution: I started using a BlockingCollection<string> pool in the algorithm below, but I see that BlockingCollection requires a call to CompleteAdding, which I can't do, because I always get incoming threads (I hardcoded to 10 in the example below for debugging purposes), think web requests.
public class MyTest {
private const int MaxThreads = 3;
private BlockingCollection<string> pool;
public MyTest() {
pool = new BlockingCollection<string>(MaxThreads);
}
public void Go() {
var addSuccess = this.pool.TryAdd(string.Format("thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
if (!addSuccess) Console.WriteLine(string.Format("thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
Console.WriteLine(string.Format("Adding thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
Console.WriteLine(string.Format("Pool size: {0}", pool.Count));
// simulate work
Thread.Sleep(1000);
Console.WriteLine("Thread ID#{0} " + Thread.CurrentThread.ManagedThreadId + " is done doing work.");
string val;
var takeSuccess = this.pool.TryTake(out val);
if (!takeSuccess) Console.WriteLine(string.Format("Failed to take out thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
Console.WriteLine("Taking out " + val);
Console.WriteLine(string.Format("Pool size: {0}", pool.Count));
Console.WriteLine(Environment.NewLine);
}
}
static void Main()
{
var t = new MyTest();
Parallel.For(0, 10, x => t.Go());
}
Any ideas on how I can better achieve this?
Thanks!
P.S. Multi-threading newbie here, if you have any suggestions for reading materials, I would greatly appreciate them.
LE: Based on the answers I got, I was able to achieve the desired behavior using this algorithm:
public class MyTest {
private const int MaxThreads = 3;
private SemaphoreSlim semaphore;
public MyTest() {
semaphore = new SemaphoreSlim(MaxThreads, MaxThreads);
}
public void Go() {
Console.WriteLine(string.Format("In comes thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
semaphore.Wait();
try {
Console.WriteLine(string.Format("Serving thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
// simulate work
Thread.Sleep(1000);
Console.WriteLine(string.Format("Out goes thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
}
finally {
semaphore.Release();
}
}
}
static void Main()
{
var t = new MyTest();
Parallel.For(0, 10, x=> t.Go());
}
If you want to protect certain number of threads which can access a critical region at a time, you'll have to use Semaphore or SemaphoreSlim. I suggest latter one, which is light weight when compared to former.
One disadvantage of SemaphoreSlim is that they won't work cross process, but that's fine we have Semaphore to help.
You can test whether the Semaphore is full via one of the Wait methods provided by the framework with a timeout.
SemaphoreSlim semaphore = new SemaphoreSlim(3, 3);
if (!semaphore.Wait(0))
{
//Already semaphore full.
//Handle it as you like
}
http://www.albahari.com/threading/ is a very good resource for threading.

How can i use AutoResetEventHandler to signal Main thread function to start threads again once the first set of worker threads are done processing

Requirement :- At any given point of time only 4 threads should be calling four different functions. As soon as these threads complete, next available thread should call the same functions.
Current code :- This seems to be the worst possible way to achieve something like this. While(True) will cause unnecessary CPU spikes and i could see CPU rising to 70% when running the following code.
Question :- How can i use AutoResetEventHandler to signal Main thread Process() function to start next 4 threads again once the first 4 worker threads are done processing without wasting CPU cycles. Please suggest
public class Demo
{
object protect = new object();
private int counter;
public void Process()
{
int maxthread = 4;
while (true)
{
if (counter <= maxthread)
{
counter++;
Thread t = new Thread(new ThreadStart(DoSomething));
t.Start();
}
}
}
private void DoSomething()
{
try
{
Thread.Sleep(50000); //simulate long running process
}
finally
{
lock (protect)
{
counter--;
}
}
}
You can use TPL to achieve what you want in a simpler way. If you run the code below you'll notice that an entry is written after each thread terminates and only after all four threads terminate the "Finished batch" entry is written.
This sample uses the Task.WaitAll to wait for the completion of all tasks. The code uses an infinite loop for illustration purposes only, you should calculate the hasPendingWork condition based on your requirements so that you only start a new batch of tasks if required.
For example:
private static void Main(string[] args)
{
bool hasPendingWork = true;
do
{
var tasks = InitiateTasks();
Task.WaitAll(tasks);
Console.WriteLine("Finished batch...");
} while (hasPendingWork);
}
private static Task[] InitiateTasks()
{
var tasks = new Task[4];
for (int i = 0; i < tasks.Length; i++)
{
int wait = 1000*i;
tasks[i] = Task.Factory.StartNew(() =>
{
Thread.Sleep(wait);
Console.WriteLine("Finished waiting: {0}", wait);
});
}
return tasks;
}
One other thing, from the textual requirement section on your question I'm lead to believe that a batch of four new threads should only start after all previously four threads completed. However the code you posted is not compatible with that requirement, since it starts a new thread immediately after a previous thread terminate. You should clarify what exactly is your requirement.
UPDATE:
If you want to start a thread immediately after one of the four threads terminate you can still use TPL instead of starting new threads explicitly but you can limit the number of running threads to four by using a SemaphoreSlim. For example:
private static SemaphoreSlim TaskController = new SemaphoreSlim(4);
private static void Main(string[] args)
{
var random = new Random(570);
while (true)
{
// Blocks thread without wasting CPU
// if the number of resources (4) is exhausted
TaskController.Wait();
Task.Factory.StartNew(() =>
{
Console.WriteLine("Started");
Thread.Sleep(random.Next(1000, 3000));
Console.WriteLine("Completed");
// Releases a resource meaning TaskController.Wait will unblock
TaskController.Release();
});
}
}

Return values from two long running methods, using threads

I have a thread that connects to two network resources. Each time I attempt a connection, it can take 10 seconds for a reply.
void MyThread()
{
//this takes ten seconds
Resource r1 = MySystem.GetResource(ipAddress1);
//this takes ten seconds
Resource r2 = MySystem.GetResource(ipAddress2);
//do stuff with ep1 and ep2
}
Total time is twenty seconds, but I'd really like it to take only ten seconds -- launching threads each time I call GetResource, receiving a reply and then joining each thread to return control.
What's the best way to do this? Launch two threads that each return a value? Anonymous methods that take references to local variables? My head is spinning. Code is appreciated.
How about
Resource r1 = null; // need to initialize, else compiler complains
Resource r2 = null;
ThreadStart ts1 = delegate {
r1 = MySystem.GetResource(ipAddress1);
};
ThreadStart ts2 = delegate {
r2 = MySystem.GetResource(ipAddress2);
};
Thread t1 = new Thread(ts1);
Thread t2 = new Thread(ts2);
t1.Start();
t2.Start();
// do some useful work here, while the threads do their thing...
t1.Join();
t2.Join();
// r1, r2 now setup
Short and sweet.
The easiest way that occurs to me to do so is to parallelize one of the calls on a worker thread while having the main thread perform the second initialization and wait. The following snipet should help to illustrate:
ManualResetEvent r1Handle = new ManualResetEvent(false);
Resource r1 = null;
Resource r2 = null;
// Make the threadpool responsible for populating the
// first resource.
ThreadPool.QueueUserWorkItem( (state) =>
{
r1 = MySystem.GetResource(ipAddress1);
// Set the wait handle to signal the main thread that
// the work is complete.
r1Handle.Set();
});
// Populate the second resource.
r2 = MySystem.GetResource(ipAddress2);
// Wait for the threadpool worker to finish.
r1Handle.WaitOne();
// ... Do more stuff
For a more detailed discussion of thread synchronization techniques, you may wish to visit the MSDN article on the topic: http://msdn.microsoft.com/en-us/library/ms173179.aspx
These are always fun questions to ponder, and of course there's multiple ways to solve it.
One approach that's worked well for me is to provide a callback method that each thread uses to pass back results and status. In the following example, I use a List to keep track of running threads and put the results in a Dictionary.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Timers;
namespace ConsoleApplication1
{
class Program
{
static Dictionary threadResults = new Dictionary();
static int threadMax = 2;
static void Main(string[] args)
{
List<Thread> runningThreads = new List<Thread>();
for (int i = 0; i < threadMax; i++)
{
Worker worker = new Worker();
worker.Callback = new Worker.CallbackDelegate(ThreadDone);
Thread workerThread = new Thread(worker.DoSomething);
workerThread.IsBackground = true;
runningThreads.Add(workerThread);
workerThread.Start();
}
foreach (Thread thread in runningThreads) thread.Join();
}
public static void ThreadDone(int threadIdArg, object resultsArg)
{
threadResults[threadIdArg] = resultsArg;
}
}
class Worker
{
public delegate void CallbackDelegate(int threadIdArg, object resultArg);
public CallbackDelegate Callback { get; set; }
public void DoSomething()
{
// do your thing and put it into results
object results = new object();
int myThreadId = Thread.CurrentThread.ManagedThreadId;
Callback(myThreadId, results);
}
}
}
Try this on MSDN: "Asynchronous programming using delegates."
http://msdn.microsoft.com/en-us/library/22t547yb.aspx
-Oisin

Categories

Resources