Im trying to see a performance difference between the following two programs (was expecting). But I find no difference. Is this normal? Im running on a Windows Core 2 Duo M/C
Visual Studio 2010 Express Edition
Program 1 (averaged over 100 runs: 824.11 ms):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
namespace MultiThreading
{
class Program
{
public static Stopwatch stopwatch;
static void Main(string[] args)
{
stopwatch = new Stopwatch();
stopwatch.Start();
//Thread t = new Thread(WriteY);
//t.Start();
for (int i = 0; i < 10000; i++)
{
Console.Write("x{0} ", i);
}
WriteY();
Console.WriteLine("Time taken in milliseconds: {0}", stopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
static void WriteY()
{
for (int i = 0; i < 10000; i++)
{
Console.Write("y{0} ", i);
}
//Console.WriteLine("Time taken in milliseconds: {0}", stopwatch.ElapsedMilliseconds);
//Console.ReadLine();
}
Program 2(averaged over 100 runs: 828.11 ms):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
namespace MultiThreading
{
class Program
{
public static Stopwatch stopwatch;
static void Main(string[] args)
{
stopwatch = new Stopwatch();
stopwatch.Start();
Thread t = new Thread(WriteY);
t.Start();
for (int i = 0; i < 10000; i++)
{
Console.Write("x{0} ", i);
}
//WriteY();
Console.WriteLine("Time taken in milliseconds: {0}", stopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
static void WriteY()
{
for (int i = 0; i < 10000; i++)
{
Console.Write("y{0} ", i);
}
//Console.WriteLine("Time taken in milliseconds: {0}", stopwatch.ElapsedMilliseconds);
//Console.ReadLine();
}
}
}
My guess is that both are bound by the speed of Console.Write which presumably needs to lock the resource (the screen) so that only one thread accesses it at a time.
The problem is that your application is IO-bound because you use Console.WriteLine all the time. If you do something which isn't using IO you will see a boost.
And as mentioned in the other answer WriteLine does indeed synchronize: Calling Console.WriteLine from multiple threads
Related
The semaphore means to specify the count how many threads can enter into critical region at a time.
The following code set the count is 5.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static Semaphore semaphore = new Semaphore(5, 5);
static void Main(string[] args)
{
Task.Factory.StartNew(() =>
{
for (int i = 1; i <= 15; ++i)
{
PrintSomething(i);
if (i % 5 == 0)
{
Thread.Sleep(2000);
}
}
});
Console.ReadLine();
}
public static void PrintSomething(int number)
{
semaphore.WaitOne();
Console.WriteLine(number);
semaphore.Release();
}
}
}
Which means each time we can have 5 threads running at any time. The printing result verifies the point.
My question is that I don't see so many threads running. Say 15 threads running, each time only can let 5 threads to be coexisting. There are only two threads.
Am I misunderstood something?
You start one additional thread using Task.Factory.StartNew() and that's it. In that thread you are calling the PrintSomething() method sequentially, so your thread output screenshot is correct.
Change your code as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SempahoreTest1
{
class Program
{
static Semaphore semaphore = new Semaphore(5, 5);
static void Main(string[] args)
{
for (int i = 1; i <= 15; ++i)
{
Task.Factory.StartNew((state) =>
{
int number = (int)state;
PrintSomething(number);
if (i % 5 == 0)
{
Thread.Sleep(2000);
}
}, i);
}
Console.ReadLine();
}
public static void PrintSomething(int number)
{
semaphore.WaitOne();
try
{
Console.WriteLine("Thread: {0}, Number: {1}", Thread.CurrentThread.ManagedThreadId, number);
}
finally
{
semaphore.Release();
}
}
}
}
Update:
A better explanation, how a semaphore works, would be:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SempahoreTest1
{
class Program
{
static Semaphore semaphore = new Semaphore(5, 5);
static Random random = new Random();
static void Main(string[] args)
{
Parallel.For(1, 16, PrintSomething);
Console.ReadLine();
}
public static void PrintSomething(int number)
{
semaphore.WaitOne();
try
{
Console.WriteLine("Thread: {0}, Number: {1}, Access granted", Thread.CurrentThread.ManagedThreadId, number);
// sleep to simulate long running method
Thread.Sleep(random.Next(1000, 5000));
}
finally
{
semaphore.Release();
Console.WriteLine("Thread: {0}, Number: {1}, Semaphore released", Thread.CurrentThread.ManagedThreadId, number);
}
}
}
}
The parallel loop calls PrintSomething() from different threads. On every call the semaphore counter is decreased, until it reaches 0. The next call of PrintSomething() blocks on semaphore.WaitOne(), until the first calls semaphore.Release(), that increments the semaphore counter again. And so on...
The first 5 calls are very fast, because the maximum semaphore count (5) is available. Then, due to the different sleep times, the method call outputs show you, how the semaphore works.
I wrote app that is doing repeatedly some task every minute. Problem is that sometimes ( inner calculations ( because CPU was busy or because of any reasons) take more than 50 seconds, then I have to close app. "App monitor that is independent application will turn it on again" so that is not a problem. I implemented watchdog which can tell me if time is finished and then shut down my app.
And my question is if I'm doing it correctly. I test this solution for some time and it looks like working ok.
Main program
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AppTimer
{
class Program
{
public static appScheduler ap = new appScheduler();
static void Main(string[] args)
{
Console.WriteLine("Press ESC to stop");
while (ap.getWatchDogSeconds() < 55)
{
if (Console.KeyAvailable)
{
if (Console.ReadKey(true).Key == ConsoleKey.Escape)
{
break;
}
}
Thread.Sleep(100);
}
Console.WriteLine("Watchdog Fired ....sw finished !!");
Thread.Sleep(2000);
}
/// <summary>
/// Emulation of long calculation process
/// </summary>
public static void doJob()
{
Console.Clear();
Thread.Sleep(5000);
Console.WriteLine("Busy...");
Console.WriteLine("WatchDog Seconds : " + ap.getWatchDogSeconds());
ap.setWatchDogSeconds(40);
Console.WriteLine("Waiting longer than normal...");
Console.WriteLine("WatchDog Seconds : " + ap.getWatchDogSeconds());
Thread.Sleep(5000);
Console.WriteLine("Maybe sth is down !! or too busy");
Console.WriteLine("WatchDog Seconds : " + ap.getWatchDogSeconds());
while (true)
{
Thread.Sleep(200);
}
}
}
}
Below appScheduler class :
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AppTimer
{
public class appScheduler
{
static readonly object _lockerWD = new object();
static int minutes = 0;
static int seconds = 50;
static int days = 0;
static int hours = 0;
private static Task calculationsTask;
private int watchDogSeconds = 0;
private int maxSecondsForWatchdog = 50;
public appScheduler()
{
startTimer();
startWatchdogTimer();
}
private void ExecuteSeconds()
{
if (seconds == 0)
{
executeRepeatdTask();
}
calculateTime();
showTimerScreen();
}
private void executeRepeatdTask()
{
calculationsTask = Task.Factory.StartNew(() =>
Program.doJob());
}
public void startTimer()
{
var timer = new System.Threading.Timer((e) =>
{
ExecuteSeconds();
}, null, 0, 1000);
}
public void startWatchdogTimer()
{
var timer = new System.Threading.Timer((e) =>
{
ExecuteSecondsWatchDog();
}, null, 0, 1000);
}
private void ExecuteSecondsWatchDog()
{
Trace.WriteLine("Current amount of WD Seconds : " + watchDogSeconds);
increaseWatchDogSeconds();
}
private void showTimerScreen()
{
if ((calculationsTask == null) || (calculationsTask.IsCompleted == true))
{
//making watchdog zero if time is running and we are showing it!!
Console.Clear();
Console.WriteLine("This is software v1.2");
Console.WriteLine(String.Format("Current execution time : {0} days : {1} hours : {2} : minutes : {3} seconds",
days, hours, minutes, seconds));
Console.WriteLine("WatchDog Seconds : " + watchDogSeconds);
setWatchDogSeconds(0);
}
}
private void calculateTime()
{
seconds++;
if (seconds > 59)
{
seconds = 0;
minutes++;
if (minutes > 59)
{
minutes = 0;
hours++;
if (hours > 23)
{
hours = 0;
days++;
}
}
}
}
public int getMinutes()
{
return minutes;
}
public int getWatchDogSeconds()
{
return watchDogSeconds;
}
public void setWatchDogSeconds(int seconds)
{
Monitor.Enter(_lockerWD);
watchDogSeconds = seconds;
Monitor.Exit(_lockerWD);
}
public void increaseWatchDogSeconds()
{
var seconds = getWatchDogSeconds();
setWatchDogSeconds(seconds += 1);
if (seconds > maxSecondsForWatchdog)
{
Trace.WriteLine(string.Format("More than {0} seconds!", maxSecondsForWatchdog)); ;
Environment.Exit(0);
}
}
}
}
I do a great deal of workflow type tasks every day. I have tried to kick off jobs in the past the way you have here. The only time I use Thread.Sleep is to simulate some long running process in a test environment. I would look into using SetTimer. Also using Thread.Sleep in a loop is not going to give you accurate results. Now, that being said, keeping this running is going to be tricky.
Ultimately kicking off jobs on a regular basis is a breeze if you have an SQL server and can set the call up in an SSIS package. Especially if you are are trying to do this in a web application which might just stop running after a period of time. Good Luck
I'm working on my multi-threading password cracker, only numbers. It must show how much time has passed to find the password. I used Stopwatch to find it, but in functions Stopwatch doesn't work. Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
int psw = 14995399;
Stopwatch time = new Stopwatch();
Thread Thread1 = new Thread(islem1);
Thread Thread2 = new Thread(islem2);
Thread Thread3 = new Thread(islem3);
Thread Thread4 = new Thread(islem4);
time.Start();
Thread1.Start();
Thread2.Start();
Thread3.Start();
Thread4.Start();
Thread.Sleep(1000);
time.Stop();
System.Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
static void islem1()
{
for (int i = 00000000; i < 25000000; i++)
{
int psw = 14995399;
if (i == psw)
{
System.Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
static void islem2()
{
for (int i = 25000000; i < 50000000; i++)
{
int psw = 14995399;
if (i == psw)
{
System.Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
static void islem3()
{
for (int i = 50000000; i < 75000000; i++)
{
int psw = 14995399;
if (i == psw)
{
System.Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
static void islem4()
{
for (int i = 75000000; i < 100000000; i++)
{
int psw = 14995399;
if (i == psw)
{
System.Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
}
}
It's because your variable
Stopwatch time = new Stopwatch();
declared outside the visibility functions. The scope of visibility the var is your function Main. You can pass Stopwatch as a parameter to your functions:
Thread1.Start(time);
Or declare it as a class field:
class Program
{
private static Stopwatch time = new Stopwatch();
...
}
Note that you have just one Stopwatch instance then if you stop it in one thread it'll stopped in all application and elapsed time will not changed after that.
Then you should delete time.Stop(); from your Main method because it can caused the result in cased when your threads works longet then 1 second.
Also it's no reason to call Thread.Sleep(). Just delete this lines and your code continues work as expected.
Finally you can delete Console.ReadKey() from your thread functions because your main-thread already waits for user input.
The whole solution with configurable threads count can illustrate interesting results for different number of threads. Try the code below which can illustrate work with thread parameters and reduce lines of code:
using System;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication4
{
internal class Program
{
private class BruteforceParams
{
public int StartNumber { get; set; }
public int EndNumber { get; set; }
}
private const int password = 14995399;
private static readonly Stopwatch time = new Stopwatch();
private static void Main(string[] args)
{
const int maxPassword = 100000000;
Console.WriteLine("Enter number of threads: ");
var threadsCountString = Console.ReadLine();
var threadsCount = int.Parse(threadsCountString);
var threads = new Thread[threadsCount];
for (int i = 0; i < threadsCount; i++)
{
var thread = new Thread(Bruteforce);
threads[i] = thread;
}
time.Start();
for (int i = 0; i < threadsCount; i++)
{
threads[i].Start(new BruteforceParams { StartNumber = i * maxPassword / threadsCount, EndNumber = (i + 1) * maxPassword / threadsCount });
}
Console.ReadKey();
}
private static void Bruteforce(object param)
{
var bp = (BruteforceParams) param;
for (int i = bp.StartNumber; i < bp.EndNumber; i++)
{
if (i == password)
{
Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
}
}
}
}
}
How do you think time.Stop(); going to work inside your function body islem1() or any other since you have defined the stopwatch inside Main() function body. You are bound to get compilation error saying time doesn't exist in current context.
static void islem1()
{
.............
time.Stop(); // this line of code
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
Rather, you can create a separate watch per method and report that
static void islem1()
{
StopWatch time = Stopwatch.StartNew();
time.Stop(); // this line of code
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
It's going to be difficult to extract meaningful timings using a single Stopwatch instance.
You might chose to make your timing measurements using a different pattern that uses a new Stopwatch for each measurement.
void Main()
{
var t1 = new Thread(_ => {
var sw = Stopwatch.StartNew();
DoSomething();
Console.WriteLine("took {0}ms", sw.ElapsedMilliseconds);
});
var t2 = new Thread(_ => {
var sw = Stopwatch.StartNew();
DoSomethingElse();
Console.WriteLine("took {0}ms", sw.ElapsedMilliseconds);
});
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.ReadKey();
}
void DoSomething()
{
//do something
}
void DoSomethingElse()
{
//do something
}
I am new to C# and still learning the threading concept. I wrote a program which is as follows
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication17
{
class Program
{
static void Main(string[] args)
{
System.Threading.ThreadStart th1 = new System.Threading.ThreadStart(prnt);
Thread th = new Thread(th1);
th.Start();
bool t = th.IsAlive;
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i + "A");
}
}
private static void prnt()
{
for (int i = 0; i < 10; i ++)
{
Console.WriteLine(i + "B");
}
}
}
}
I am expecting an output like :-
1A
2A
1B
3A
2B...
as I believe that both main thread and newly created thread should be executing simultaneously.
But the output is ordered , first the prnt function is called and then the Main method for loop is executed.
maybe a cicle of 10 is not enough to see the two thread running at same time.
use a longer loop or put a Thread.Sleep (100) within cycle iteration.
Starting a thread is quite expensive. What it happens, probably, is that you Main loop get executed before thread loop start, due to the time required for a thread to start
I agree with previous answers you need to add Thread.Sleep(some seconds * 1000)
I recommend you read this article about thread
https://msdn.microsoft.com/ru-ru/library/system.threading.thread(v=vs.110).aspx
static void Main(string[] args)
{
Thread th = new Thread(prnt);
th.Start();
for (int i = 0; i < 10; i++)
{
//sleep one second
Thread.Sleep(1000);
Console.WriteLine(i + "A");
}
//join the basic thread and 'th' thread
th.Join();
}
private static void prnt()
{
for (int i = 0; i < 10; i++)
{
//sleep one second
Thread.Sleep(1000);
Console.WriteLine(i + "B");
}
}
Updated: A process is used to isolate applications and threads run in the context of that process.
This way, it makes easier for the OS to manage different apps, managing crashes and context switching (slots of time provided to each app to be executed by the CPU). The idea behind is simply run threads during a predefined slot of time, when the time permitted for an app to run is over, the CPU switches to other thread to be executed.
Use the Threading class for small asynchronous tasks in your applications.
See how in the following example you can create a new thread using the System.Threading namespace. Notice how t.Join() is called to wait for the new thread to finish.
Note that the Spleep(1) will force to change the context and that's is what makes the difference with you example. Try to change it back to zero and see the results.
using System;
using System.Threading;
namespace Chapter1
{
public static class Threads1
{
public static void ThreadMethod()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("ThreadProc: {0}", i);
Thread.Sleep(1);
}
}
public static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(ThreadMethod));
t.Start();
for (int i = 0; i < 4; i++)
{
Console.WriteLine("Main thread: Do some work.");
Thread.Sleep(1);
}
t.Join();
Console.Read();
}
}
}
// OUTPUT:
//Main thread: Do some work.
//ThreadProc: 0
//ThreadProc: 1
//Main thread: Do some work.
//ThreadProc: 2
//Main thread: Do some work.
//ThreadProc: 3
//Main thread: Do some work.
//ThreadProc: 4
//ThreadProc: 5
//ThreadProc: 6
//ThreadProc: 7
//ThreadProc: 8
//ThreadProc: 9
What I'm trying to do is queue up a big list of similar tasks. The time it takes each task to complete is small but there are a lot of them. For each item in the list, I create a delegate and call the delegate.BeginInvoke method then I move to creating the next one.
I would expect in the below example that I would get at least one "****** End Invoke ****" to occur BEFORE all of the begin invokes are called. Instead, it looks like the compiler is starting all of my begin invokes before any end invokes are received.
Is this normal behavior? Is there another way I can send off a task/method on another thread and receive it back while continuing to spur up more tasks?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace AsyncResultTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting");
for (int i = 0; i < 100; i++)
{
delMeth d = new delMeth(sleepMethod);
Console.WriteLine(string.Format("Calling the begin invoke from thread: {0} for ID: {1}", Thread.CurrentThread.ManagedThreadId.ToString(), i.ToString()));
IAsyncResult ar = d.BeginInvoke(i, callbackMessage, d);
}
Console.ReadLine();
}
private delegate int delMeth(int id);
private static int sleepMethod(int id)
{
Console.WriteLine(Environment.NewLine + String.Format("Thread: {0} is sleeping. Delegate id is {1}", Thread.CurrentThread.ManagedThreadId.ToString(),id.ToString()));
Console.WriteLine(String.Format("Thread Properties IsThreadPoolThread? = {0} isThreadBackground? = {1} ThreadState: = {2}", Thread.CurrentThread.IsThreadPoolThread.ToString(), Thread.CurrentThread.IsBackground.ToString(), Thread.CurrentThread.ThreadState.ToString()));
Console.WriteLine("");
Thread.Sleep(100);
return id;
}
private static void callbackMessage(IAsyncResult ar)
{
delMeth d = (delMeth)ar.AsyncState;
int result = d.EndInvoke(ar);
Console.WriteLine(Environment.NewLine + "************************ END INVOKE *****************************");
Console.WriteLine(String.Format("Delegate was just called back for id: {0}", result.ToString()));
}
}
}
Unfortunately I have to design this using .NET 3.5 so Task Asynchronous Processing is not available to me.
USR is correct. Everything is functioning how I would expect it to. If i sleep for 10 ms then I see EndInvokes come back in the middle of BeginInvokes.
Thanks USR.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace AsyncResultTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting");
for (int i = 0; i < 150; i++) {
delMeth d = new delMeth(sleepMethod);
Console.WriteLine(string.Format("Calling the begin invoke from thread: {0} for ID: {1}", Thread.CurrentThread.ManagedThreadId.ToString(), i.ToString()));
IAsyncResult ar = d.BeginInvoke(i, new AsyncCallback(callbackMessage), d);
}
Console.ReadLine();
}
private delegate int delMeth(int id);
private static int sleepMethod(int id)
{
Console.WriteLine(Environment.NewLine + String.Format("Thread: {0} is sleeping. Delegate id is {1}", Thread.CurrentThread.ManagedThreadId.ToString(),id.ToString()));
Console.WriteLine(String.Format("Thread Properties IsThreadPoolThread? = {0} isThreadBackground? = {1} ThreadState: = {2}", Thread.CurrentThread.IsThreadPoolThread.ToString(), Thread.CurrentThread.IsBackground.ToString(), Thread.CurrentThread.ThreadState.ToString()));
Console.WriteLine("");
Thread.Sleep(10);
return id;
}
private static void callbackMessage(IAsyncResult ar)
{
delMeth d = (delMeth)ar.AsyncState;
int result = d.EndInvoke(ar);
Console.WriteLine(Environment.NewLine + "************************ END INVOKE *****************************");
Console.WriteLine(String.Format("Delegate was just called back for id: {0}", result.ToString()));
}
}
}