How does semaphore.CurrentCount work in this context? - c#

I just started learning SemaphoreSlim but how does the semaphore.CurrentCount increments and decrements in this program? From my understanding, when semaphore.Wait() is called the release counter is decremented by 1 and when semaphore.Release(), two threads are allowed to execute but how does the semaphore.CurrentCount get incremented? does it start from 0 or 1 ?
var semaphore = new SemaphoreSlim(2, 10);
for (int i = 0; i < 20; i++)
{
Task.Factory.StartNew(() =>
{
Console.WriteLine("Entering task " + Task.CurrentId);
semaphore.Wait(); //releasecount--
Console.WriteLine("Processing task " + Task.CurrentId);
});
}
while (semaphore.CurrentCount <= 2)
{
Console.WriteLine("Semaphore count: " + semaphore.CurrentCount);
Console.ReadKey();
semaphore.Release(2);
}
Console.ReadKey();

The semaphore is like a room with a certain capacity. With SemaphoreSlim you are specifying the initial capacity and the maximum. After it reach the maximum, no one can enter anymore to the room. Per every item that leaves the room, only one is allowed to enter.
The CurrentCount gets the number of remaining threads that can enter the room.
for (int i = 0; i < 20; i++)
{
Task.Factory.StartNew(() =>
{
Console.WriteLine("Entering task " + Task.CurrentId);
semaphore.Wait(); //only from 2 - 10 threads can be at the time
Console.WriteLine("Processing task " + Task.CurrentId);
});
}
And here
while (semaphore.CurrentCount <= 2)
if at that moment the number of remaining threads is less than 2 then you are releasing two spaces on the room

Wait decrements it and Release increments it.

Related

C# first fit Algorithm output

I've been given a homework assignment to code the first-fit algorithm, it's meant to assign a set number of jobs to a set number of memory blocks according to the first-Fit algorithm. So far I have the algorithm working and assigning jobs correctly; however, my problem is when my queued jobs are output to the console my loop doesn't iterate through all jobs being sent to queue, it just shows the initial job being sent to queue and its size until all jobs that were meant to be sent to queue have been iterated through.
This might be very simple but I can't seem to figure it out.... Anything else needed just ask and I can provide. Thank you.
public void firstFit(int counter, int JobIndex)
{
Counter = counter;
jobIndex = JobIndex;
do {
if (jobSize[jobIndex] > memorySize[Counter-1])
{
Counter += 1;
}
else
{
Console.Text += Environment.NewLine + "Job " + (jobIndex+1) + " of size "
+ jobSize[jobIndex] +
" has been loaded into memory block:"
+ Counter;
memorySize[Counter-1] = memorySize[Counter-1]-jobSize[jobIndex];
Console.Text += Environment.NewLine + "The size of memory block " + Counter + " is now " + memorySize[Counter-1];
Counter = 1;
jobIndex += 1;
}
} while (Counter <= blocks && jobIndex < jobs);
for (int i = 0; i < jobs-jobIndex; i++ ){
jobQ = jobIndex;
if (jobQ < jobs)
{
Console.Text += Environment.NewLine + "Job " + (jobQ+1) + " of size " + jobSize[jobQ] + " is sent to waiting queue!";
}
}
Job 1 of size 45 has been loaded into memory block:1 The size of
memory block 1 is now 16
Job 2 of size 1230 has been loaded into memory block:2 The size of
memory block 2 is now 410
Job 3 of size 325 has been loaded into memory block:2 The size of
memory block 2 is now 85
Job 4 of size 303 has been loaded into memory block:3 The size of
memory block 3 is now 131
Job 5 of size 1178 has been loaded into memory block:5 The size of
memory block 5 is now 393
Job 6 of size 1276 has been loaded into memory block:6 The size of
memory block 6 is now 426
Job 7 of size 965 has been loaded into memory block:7 The size of
memory block 7 is now 322
Job 8 of size 537 is sent to waiting queue!
Job 8 of size 537 is sent to waiting queue!
Job 8 of size 537 is sent to waiting queue!
You have this code at the end:
for (int i = 0; i < jobs-jobIndex; i++ )
{
jobQ = jobIndex;
if (jobQ < jobs)
{
Console.Text += Environment.NewLine + "Job " + (jobQ+1) + " of size " +
jobSize[jobQ] + " is sent to waiting queue!";
}
}
The value of jobQ is the same each time through the loop, so of course it's going to print the same thing every time. Is it possible you meant the first line in the loop to read:
jobQ = jobIndex + i;
??
Sorted. Thank you Ryan for pointing me in the right direction. Problem was i wasn't trying to get the job number of all the values that needed to go into the Queue, i was just getting the job number of jobQ+1, which would always be the same job, the first job that didn't fit. The same for my jobSize.
Here's the bit of code i had to change:
for (int i = 0; i < jobs-jobIndex; i++ ){
jobQ = jobIndex;
if (jobQ < jobs)
{
Console.Text += Environment.NewLine + "Job " + (jobQ+(i+1)) + " of size " +
jobSize[jobQ+i]) + " is sent to waiting queue!";
}
}

MaxDegreeOfParallelism = 2 shows 3 threads

WHen I run the following code:
public static double SumRootN(int root)
{
double result = 0;
for (int i = 1; i < 10000000; i++)
{
result += Math.Exp(Math.Log(i) / root);
}
return result;
}
static void Main()
{
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 2; // -1 is for unlimited. 1 is for sequential.
try
{
Parallel.For(
0,
9,
options,
(i) =>
{
var result = SumRootN(i);
Console.WriteLine("Thread={0}, root {0} : {1} ",Thread.CurrentThread.ManagedThreadId, i, result);
});
);
}
catch (AggregateException e)
{
Console.WriteLine("Parallel.For has thrown the following (unexpected) exception:\n{0}", e);
}
}
I see that the output is:
There are 3 thread Ids here, but I have specified that the MaxDegreeOFParallelism is only 2. So why is there 3 threads doing the work instead of 2?
Quote from http://msdn.microsoft.com/en-us/library/system.threading.tasks.paralleloptions.maxdegreeofparallelism(v=vs.110).aspx
By default, For and ForEach will utilize however many threads the underlying scheduler provides, so changing MaxDegreeOfParallelism from the default only limits how many concurrent tasks will be used.
Translation: only 2 threads will be running at any given moment, but more (or even less) than 2 may be used out of the thread pool. You can test this with another writeline at the start of the task, you'll see that no 3 threads will enter concurrently.

Iterating until int.MaxValue reached

As a little test I wanted to see how long it would take to count to int.MaxValue in a C# console application. Every few hours I checked the progress. Last night when I thought the program would be done executing, it was executing back to 0. I'm not sure why that happened and I was wondering if anyone could explain it to me. What it did was that it counted to 2,147,483,647 then when this value was reached it began counting backwards to zero. Even though it appeared to be counting backwards, the value had a negative number. I wonder if I needed to use the absolute value of int.MaxValue. Anyway, I was just curious if anyone could see what I'm not seeing. Here is my code. Thanks
static void Main(string[] args)
{
int maxInt = int.MaxValue;
int numToCountTo = maxInt;
//int numToCountTo = 1000000;
try
{
Console.WriteLine(DateTime.Now);
Console.WriteLine("Press any key to begin.");
Console.ReadLine();
Stopwatch sw = new Stopwatch();
sw.Start();
for (int counter=0; counter <=numToCountTo ; counter++)
{
Console.WriteLine(counter);
}
sw.Stop();
TimeSpan ts = sw.Elapsed;
// Format and display the TimeSpan value.
string elapsedTime = String.Format("{0:00 Hours}, {1:00 Minutes}, {2:00 Seconds}, {3:00 Milliseconds}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
// ("#,#") places a comma between every 3 digits
Console.WriteLine("It took " + elapsedTime + " to count to " + numToCountTo.ToString("#,#"));
Console.WriteLine("Press Enter key to continue.");
Console.ReadLine();
}
catch (Exception ex)
{
throw new Exception("Exception Reached: " + ex.Message)
}
}
Your for loop:
for (int counter=0; counter <=numToCountTo ; counter++)
is incorrect. It will execute while counter <= int.MaxValue which is ALWAYS true. When it increments it it will roll to int.MinValue and keep incrementing.
Change it to
for (int counter=0; counter < numToCountTo ; counter++)
or use a long for your loop counter:
for (long counter=0; counter <= numToCountTo ; counter++)
You can also use a do...while loop since the loop is executed before the breaking condition is evaluated:
int counter = 0;
do
{
...
counter++;
}
while(counter < numToCountTo);
It will continue because counter will never be > than int.MaxValue, if you do int.MaxValue+1 it will wrap down to int.MinValue.
Thus, your for condition is always true.
An alternative I would recommend is either use a larger datatype for your counter like long, or change your loop to:
int counter = -1;
for(;;) // while(true)
{
counter++;
Console.WriteLine("{0}", counter);
if (counter == int.MaxValue)
{
break;
}
}
When you add 1 to an Int32.MaxValue you will end up with Int32.MinValue.
int a = Int32.MaxValue;
a++; // a is now -2147483648
It's called an overflow - the integer wraps around to the lowest possible negative value.
If you want it to stop at maxInt you should replace the <= with a < - at present you can never stop the loop as counter can never be bigger can maxIni.

Where is the race condition in this code snippet? (from C# 5.0 in a Nutshell)

This is from Joseph Albahari's excellent C# 5.0 in a Nutshell book
In one of his chapters, he mentions a race-condition in this code block ..my guess is it's meant to be pretty self-evident, as he didn't bother to specify where it was but running the code multiple times I was unable to produce the said-race condition
_button.Click += (sender, args) =>
{
_button.IsEnabled = false;
Task.Run (() => Go());
};
void Go()
{
for (int i = 1; i < 5; i++)
{
int result = GetPrimesCount (i * 1000000, 1000000);
Dispatcher.BeginInvoke (new Action (() =>
_results.Text += result + " primes between " + (i*1000000) + " and " +
((i+1)*1000000-1) + Environment.NewLine));
}
Dispatcher.BeginInvoke (new Action (() => _button.IsEnabled = true));
}
I don't agree with #Serge's answer. You don't even need multiple threads to see the problem. Try to run your code in its original form and notice the output. For me it's the following and is sometimes random (I fixed the first value):
1000000 primes between 5000000 and 5999999
1000000 primes between 5000000 and 5999999
1000000 primes between 5000000 and 5999999
1000000 primes between 5000000 and 5999999
Notice the last 2 values. They're all the same, but they should depend on i. The problem is not that the operation is not atomic, because the GUI thread will execute the actions sequentially anyway.
The reason for this occurring is that the lambda function passed to BeginInvoke takes the value of i at the moment of execution, not at the moment of initialization, so they will all see the last value of i by the time they get executed. The solution is to explicitly pass i as a parameter to the lambda like so:
for (int i = 1; i < 5; i++)
{
int result = 1000000;
Dispatcher.BeginInvoke(new Action<int>(j =>
results.Text += result + " primes between " + (j * 1000000) + " and " +
((j + 1) * 1000000 - 1) + Environment.NewLine), i);
}
This line will not be calculated atomically:
_results.Text += result + " primes between " + (i*1000000) + " and " + ((i+1)*1000000-1) + Environment.NewLine));
So being executed from 5 concurrently running threads it may produce different funny results.

Exit the loop after specific time in C#

I have a requirement in my project (C#, VS2010, .NET 4.0) that a particular for loop must finish within 200 milliseconds. If it doesn't then it has to terminate after this duration without executing the remaining iterations. The loop generally goes for i = 0 to about 500,000 to 700,000 so the total loop time varies.
I have read following questions which are similar but they didn't help in my case:
What is the best way to exit out of a loop after an elapsed time of 30ms in C++
How to execute the loop for specific time
So far I have tried using a Stopwatch object to track the elapsed time but it's not working for me. Here are 2 different methods I have tried so far:
Method 1. Comparing the elapsed time within for loop:
Stopwatch sw = new Stopwatch();
sw.Start();
for (i = 0; i < nEntries; i++) // nEntries is typically more than 500,000
{
// Do some stuff
...
...
...
if (sw.Elapsed > TimeSpan.FromMilliseconds(200))
break;
}
sw.Stop();
This doesn't work because if (sw.Elapsed > TimeSpan.FromMilliseconds(200)) takes more than 200 milliseconds to complete. Hence useless in my case. I am not sure whether TimeSpan.FromMilliseconds() generally takes this long or it's just in my case for some reason.
Method 2. Creating a separate thread to compare time:
Stopwatch sw = new Stopwatch();
sw.Start();
bool bDoExit = false;
int msLimit = 200;
System.Threading.ThreadPool.QueueUserWorkItem((x) =>
{
while (bDoExit == false)
{
if (sw.Elapsed.Milliseconds > msLimit)
{
bDoExit = true;
sw.Stop();
}
System.Threading.Thread.Sleep(10);
}
});
for (i = 0; i < nEntries; i++) // nEntries is typically more than 500,000
{
// Do some stuff
...
...
...
if (bDoExit == true)
break;
}
sw.Stop();
I have some other code in the for loop that prints some statistics. It tells me that in case of Method 2, the for loop definitely breaks before completing all the iterations but the loop timing is still 280-300 milliseconds.
Any suggestions to break a for loop strictly with-in 200 milliseconds or less?
Thanks.
For a faster comparison try comparing
if(sw.ElapsedMilliseconds > 200)
break;
You should do that check in the beggining of your loop and also during the processing, ("// Do some stuff" part of the code) because it is possible, for example, that processing starts at 190 (beginning of the loop), lasts 20 and ends at 210.
You could also measure average execution time of your processing (this is approximate because it relies on average time), this way loop should last 200 milliseconds or less, here is a demo that you can put in a Main method of a Console application and easily modify it for your application:
Stopwatch sw = new Stopwatch();
sw.Start();
string a = String.Empty;
int i;
decimal sum = 0, avg = 0, beginning = 0, end = 0;
for (i = 0; i < 700000; i++) // nEntries is typically more than 500,000
{
beginning = sw.ElapsedMilliseconds;
if (sw.ElapsedMilliseconds + avg > 200)
break;
// Some processing
a += "x";
int s = a.Length * 100;
Thread.Sleep(19);
/////////////
end = sw.ElapsedMilliseconds;
sum += end - beginning;
avg = sum / (i + 1);
}
sw.Stop();
Console.WriteLine(
"avg:{0}, count:{1}, milliseconds elapsed:{2}", avg, i + 1,
sw.ElapsedMilliseconds);
Console.ReadKey();
Another option would be to use CancellationTokenSource:
CancellationTokenSource source = new CancellationTokenSource(100);
while(!source.IsCancellationRequested)
{
// Do stuff
}
Use the first one - simple and have better chances to be precise than second one.
Both cases have the same kind of termination condition, so both should behave are more-or-less the same. Second is much more complicated due to usage of threads and Sleep, so I'd use first one. Also second one is much less precise due to sleeps.
There are abolutely no reasons for TimeSpan.FromMilliseconds(200) to take any significant amount of time (as well as calling it in every iteration).
Using cancellation token:
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)).Token;
while (!cancellationToken.IsCancellationRequested)
{
//Do stuff...
}
I don't know if this is that exactly, but I think it's worth a try using a System.Timers.Timer:
int msLimit = 200;
int nEntries = 500000;
bool cancel = false;
System.Timers.Timer t = new System.Timers.Timer();
t.Interval = msLimit;
t.Elapsed += (s, e) => cancel = true;
t.Start();
for (int i = 0; i < nEntries; i++)
{
// do sth
if (cancel) {
break;
}
}

Categories