using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication58
{
class MultiThreading
{
static void Main(string[] args)
{
MultiThreading mul = new MultiThreading();
Thread t1 = new Thread(new ThreadStart(mul.WriteX));
Thread t2 = new Thread(new ThreadStart(mul.WriteO));
t1.Priority = ThreadPriority.Lowest;
t2.Priority = ThreadPriority.Highest;
t1.Start();
t2.Start();
}
private void WriteX()
{
for (int i = 0; i < 300; i++)
{
Console.Write("X");
}
}
private void WriteO()
{
for (int i = 0; i < 300; i++)
{
Console.Write("O");
}
}
}
}
When I execute above code, I expect X's end of the printing job because I gave that method lowest priority but sometimes I get O's at the end. I mean doesn't giving high priority to 2nd thread guarantee it will finish sooner?
There is no practical guarantee about thread scheduling induced by the priority setting.
For example, the high priority thread could block on IO or a page fault. Then, another thread can execute.
This is not a good way to synchronize threads.
Three hundreds operations for CPU is part of second. I recommend you to think about your problem and applications as a statistical experiment.
Repeat your experiment many times, because running few of them is not trustworthy. It happens because population (number of iterations it is not big enough). I tried to run this application few times, but with 3 000 000 iterations and I let to write for 45 seconds (while(true) and Thread.Sleep(45000)). Task with higher priority finished first.
Your OS, CPU and PC configuration does matter.
Related
Hi I am new to multithreading and would like to ask for your advice and guidance.
We have a service running on our server to poll data for notifications on our clients. We wanted the service to process data faster. Currently, our existing service polls and processes data on a single thread which sometimes causes delay to the notifications on hourly bases. My plan is to use ThreadPool to process data concurrently. I have this piece of code that simulates my plan and idea.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Security;
using System.Text;
using System.Threading;
using System.Xml;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Web;
namespace ThreadPooling
{
class Program
{
static int nMaxRecord = 0;
static ManualResetEvent mre = new ManualResetEvent(false);
static Timer TestThread = null;
static void Main(string[] args)
{
TestThread = new Timer(new TimerCallback(ProcessWithThreadPoolMethod), null, 500, Timeout.Infinite);
Thread.Sleep(Timeout.Infinite);
}
static void ProcessWithThreadPoolMethod(object ostate) // Sample processing of data
{
nMaxRecord = 1300;
ThreadPool.SetMaxThreads(3, 0);
for (int i = 0; i < 1300; i++)
{
ThreadPool.QueueUserWorkItem(ProcessWithThreadMethod, i);
}
mre.WaitOne();
Console.WriteLine("Test");
TestThread.Change(5000, Timeout.Infinite);
}
static void ProcessWithThreadMethod(object callback)
{
for (int i = 0; i <= 10; i++)
{
Console.WriteLine((int)callback);
}
if(Interlocked.Decrement(ref nMaxRecord) == 0)
{
mre.Set();
}
}
}
}
While running the console application, I noticed that the thread count keeps increasing although I limited the maxthreads in the ThreadPool by 3. Am I doing the right thing? Would like to ask some guidance and Pros and Cons on my concept.
You should test the return value of:
ThreadPool.SetMaxThreads(3, 0); //returns false on normal machines.
It's unable to process the change due to this:
You cannot set the maximum number of worker threads or I/O completion threads to a number smaller than the number of processors on the computer. To determine how many processors are present, retrieve the value of the Environment.ProcessorCount property. In addition, you cannot set the maximum number of worker threads or I/O completion threads to a number smaller than the corresponding minimum number of worker threads or I/O completion threads. To determine the minimum thread pool size, call the GetMinThreads method.
See: MSDN
So, what you can do is something like this;
ThreadPool.SetMaxThreads(16, 16);
But I assume you were trying to down-throttle the ThreadPool. In general that's not a good idea. You'll need an alternative for such logic.
A semaphore might be an option, as described here, or the pattern #Fildor describes.
You cannot throttle the threadpool, but why not just have a simple increment/decrement counter that you check before launching a new thread ?
In pseudo code-
volatile int currentThreadCount = 0;
void myWorkLauncher()
{
while(<I have work to do>)
{
if(currentThreadCount < threshold)
{
currentThreadCount ++;
ThreadPool.QueueUserWorkItem(workerFunc);
}
else
{
Thread.Sleep(500);
}
}
Thread.Sleep(500);
}
The last line of the workedFunc just decrements the value.
You can do all sorts of fancy stuff like wrapping your workerFunc in an Action() which itself decrements the counter, preventing your workerFunc from needing any connection to the myWorkLauncher class. Alternatively you can replace the simplistic Thread.Sleep with a AutoResetEvent or similar.
When I run below code, Output is this:
When I run till 300, output is this:
When I run till 100, output is this:
Does this mean that both methods started almost at the same time?
If this is true, why do we need Parallel library if we can achieve parallelism by async-await?
using System;
using System.Threading.Tasks;
class Program
{
public static void PrintX()
{
for (int i = 0; i < 500; i++) { Console.Write("x"); }
}
public static void PrintY()
{
for (int i = 0; i < 500; i++) { Console.Write("y"); }
}
public async Task RunAsync()
{
var t1 = Task.Run(() => PrintY());
var t2 = Task.Run(() => PrintX());
await t1;
await t2;
}
static void Main(string[] args)
{
Task t = new Program().RunAsync();
t.Wait();
}
}
Ultimately you're at the mercy of the thread pool here. You have enqueued two items (Task.Run), and they will be picked up and serviced at some future time. When they start is non-deterministic, and will depend on how many available threads there are, and other factors.
They will start approximately at the same time, with no guarantees of anything (perhaps not even the order in which they start). The await will be triggered against their completion - so when you call await (or even whether you call await) won't impact them in any way. They might run in parallel, but most likely they individually run fast enough that whichever one gets started first will have completed before it tries starting the second. They might even end up running consecutively on the same thread (outputting the managed thread id would be a way to see this).
As for why we need Parallel: firstly, it pre-dates async/await by a long time; secondly it does a lot of things to allow larger scale parallelization - things like running a large sequence with concurrent processing including fixed maximum parallelization.
Just to show that it can be concurrent, here's the output from a real run where I added the Environment.CurrentManagedThreadId into the output:
main: 1
y: 3
x: 4
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
definitely concurrent, but: other runs can show very different outputs
How can I sync threads to run together.
For example:
code
Code section A
code
I want that every 5 thread will enter together to the Section A
Here's some sample code which shows how to use the Barrier class to wait for 5 threads to all be at the same point in the code before being allowed to carry on.
To try it out, run it and then ^C to stop it after a while, and inspect the times when the threads pass the barrier. You'll see that it is waiting until 5 threads are all at the barrier, then they are all released at once (whereupon the Barrier waits for the next 5 threads to be ready).
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
Barrier barrier = new Barrier(5); // 5 == #participating threads.
Action[] actions = new Action[10];
var sw = Stopwatch.StartNew();
ThreadPool.SetMinThreads(12, 12); // Prevent delay on starting threads.
// Not recommended for non-test code!
for (int i = 0; i < actions.Length; ++i)
actions[i] = () => test(barrier, sw);
Parallel.Invoke(actions);
}
static void test(Barrier barrier, Stopwatch sw)
{
int id = Thread.CurrentThread.ManagedThreadId;
Random rng = new Random(id);
while (true)
{
int wait = 5000 + rng.Next(5000);
Console.WriteLine($"[{sw.ElapsedMilliseconds:000000}] Thread {id} is sleeping for {wait} ms.");
Thread.Sleep(wait);
Console.WriteLine($"[{sw.ElapsedMilliseconds:000000}] Thread {id} is waiting at the barrier.");
barrier.SignalAndWait();
Console.WriteLine($"[{sw.ElapsedMilliseconds:000000}] Thread {id} passed the barrier.");
Thread.Sleep(1000); // This is the equivalent of your "Section A".
}
}
}
}
I am looking at the code written by my colleague:
long tim = DateTime.Now.Ticks;// get current time in ticks
long startWait = tim + TimeSpan.TicksPerSecond * 15; // add 15 seconds (in ticks) to current time
while ((tim < startWait) & !_myReader.ReaderOpen) //_myReader.ReaderOpen is external device
{
Thread.Sleep(100); // sleep for 100ms
tim = DateTime.Now.Ticks;
}
For some reason, this code does not look right. It seems like putting thread to sleep and waking it up every 100ms is huge waste of CPU.
You can use a Timer to execute periodically without forcing a thread to be sitting around doing nothing for the duration of that time. it's also possible that the reader that you're using exposes some means of notifying you when things happen so that you can respond to those events without needing to poll the object.
you could also do something like this which is exactly the same thing but different
at least you can stop the loop when myReader.ReaderOpen become true, if the 100ms is important to you
using System;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
const int TimeToWait = 15;
var sw = Stopwatch.StartNew();
var mnu = new ManualResetEvent(false);
while (sw.Elapsed.Seconds <= TimeToWait)
{
Console.WriteLine(sw.ElapsedMilliseconds);
mnu.WaitOne(100);
}
Console.ReadKey();
}
}
}
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Thread t = new Thread(() => WriteY("11"));
t.Start();
t.IsBackground = true;
Thread.CurrentThread.Priority = ThreadPriority.Highest;
for (int i = 0; i < 1000; i++) Console.Write("x");
System.Console.ReadLine();
}
static void WriteY(string ss)
{
for (int i = 0; i < 1000; i++)
Console.Write(ss);
System.Console.ReadLine();
}
}
}
Hello, I think the "x" thread should complete first, since its priority is heighest. but the result is that they are still switching.
First of all, regardless of priorities, you can not make any assumptions about which parallel job finishes first.
Also, please read this article by Jeff Atwood about why using thread priorities is a bad idea.
http://www.codinghorror.com/blog/2006/08/thread-priorities-are-evil.html
In case of tl;dr just one quote: No matter how brilliant a programmer you may be, I can practically guarantee you won't be able to outsmart the programmers who wrote the scheduler in your operating system.
If you have more then one CPU(-core) on your PC which is available this is "normal", as Thread 1 is running on CPU/core 1 and thread 2 on CPU/core 2.
I think if you reporduce the same with more threads then available cores or running e.g. Prime95 in the background to use 100% of your CPU it should make a difference, but in case of <= threads then (available) CPUs/corse the scheduler will run each thread on its own core and (if they are doing ~ the same) they will finish the same time...