How do you get list of running threads in C#? - c#
I create dynamic threads in C# and I need to get the status of those running threads.
List<string>[] list;
list = dbConnect.Select();
for (int i = 0; i < list[0].Count; i++)
{
Thread th = new Thread(() =>{
sendMessage(list[0]['1']);
//calling callback function
});
th.Name = "SID"+i;
th.Start();
}
for (int i = 0; i < list[0].Count; i++)
{
// here how can i get list of running thread here.
}
How can you get list of running threads?
On Threads
I would avoid explicitly creating threads on your own.
It is much more preferable to use the ThreadPool.QueueUserWorkItem or if you do can use .Net 4.0 you get the much more powerful Task parallel library which also allows you to use a ThreadPool threads in a much more powerful way (Task.Factory.StartNew is worth a look)
What if we choose to go by the approach of explicitly creating threads?
Let's suppose that your list[0].Count returns 1000 items. Let's also assume that you are performing this on a high-end (at the time of this writing) 16core machine. The immediate effect is that we have 1000 threads competing for these limited resources (the 16 cores).
The larger the number of tasks and the longer each of them runs, the more time will be spent in context switching. In addition, creating threads is expensive, this overhead creating each thread explicitly could be avoided if an approach of reusing existing threads is used.
So while the initial intent of multithreading may be to increase speed, as we can see it can have quite the opposite effect.
How do we overcome 'over'-threading?
This is where the ThreadPool comes into play.
A thread pool is a collection of threads that can be used to perform a number of tasks in the background.
How do they work:
Once a thread in the pool completes its task, it is returned to a queue of waiting threads, where it can be reused. This reuse enables applications to avoid the cost of creating a new thread for each task.
Thread pools typically have a maximum number of threads. If all the threads are busy, additional tasks are placed in queue until they can be serviced as threads become available.
So we can see that by using a thread pool threads we are more efficient both
in terms of maximizing the actual work getting done. Since we are not over saturating the processors with threads, less time is spent switching between threads and more time actually executing the code that a thread is supposed to do.
Faster thread startup: Each threadpool thread is readily available as opposed to waiting until a new thread gets constructed.
in terms of minimising memory consumption, the threadpool will limit the number of threads to the threadpool size enqueuing any requests that are beyond the threadpool size limit. (see ThreadPool.GetMaxThreads). The primary reason behind this design choice, is of course so that we don't over-saturate the limited number of cores with too many thread requests keeping context switching to lower levels.
Too much Theory, let's put all this theory to the test!
Right, it's nice to know all this in theory, but let's put it to practice and see what
the numbers tell us, with a simplified crude version of the application that can give us a coarse indication of the difference in orders of magnitude. We will do a comparison between new Thread, ThreadPool and Task Parallel Library (TPL)
new Thread
static void Main(string[] args)
{
int itemCount = 1000;
Stopwatch stopwatch = new Stopwatch();
long initialMemoryFootPrint = GC.GetTotalMemory(true);
stopwatch.Start();
for (int i = 0; i < itemCount; i++)
{
int iCopy = i; // You should not use 'i' directly in the thread start as it creates a closure over a changing value which is not thread safe. You should create a copy that will be used for that specific variable.
Thread thread = new Thread(() =>
{
// lets simulate something that takes a while
int k = 0;
while (true)
{
if (k++ > 100000)
break;
}
if ((iCopy + 1) % 200 == 0) // By the way, what does your sendMessage(list[0]['1']); mean? what is this '1'? if it is i you are not thread safe.
Console.WriteLine(iCopy + " - Time elapsed: (ms)" + stopwatch.ElapsedMilliseconds);
});
thread.Name = "SID" + iCopy; // you can also use i here.
thread.Start();
}
Console.ReadKey();
Console.WriteLine(GC.GetTotalMemory(false) - initialMemoryFootPrint);
Console.ReadKey();
}
Result:
ThreadPool.EnqueueUserWorkItem
static void Main(string[] args)
{
int itemCount = 1000;
Stopwatch stopwatch = new Stopwatch();
long initialMemoryFootPrint = GC.GetTotalMemory(true);
stopwatch.Start();
for (int i = 0; i < itemCount; i++)
{
int iCopy = i; // You should not use 'i' directly in the thread start as it creates a closure over a changing value which is not thread safe. You should create a copy that will be used for that specific variable.
ThreadPool.QueueUserWorkItem((w) =>
{
// lets simulate something that takes a while
int k = 0;
while (true)
{
if (k++ > 100000)
break;
}
if ((iCopy + 1) % 200 == 0)
Console.WriteLine(iCopy + " - Time elapsed: (ms)" + stopwatch.ElapsedMilliseconds);
});
}
Console.ReadKey();
Console.WriteLine("Memory usage: " + (GC.GetTotalMemory(false) - initialMemoryFootPrint));
Console.ReadKey();
}
Result:
Task Parallel Library (TPL)
static void Main(string[] args)
{
int itemCount = 1000;
Stopwatch stopwatch = new Stopwatch();
long initialMemoryFootPrint = GC.GetTotalMemory(true);
stopwatch.Start();
for (int i = 0; i < itemCount; i++)
{
int iCopy = i; // You should not use 'i' directly in the thread start as it creates a closure over a changing value which is not thread safe. You should create a copy that will be used for that specific variable.
Task.Factory.StartNew(() =>
{
// lets simulate something that takes a while
int k = 0;
while (true)
{
if (k++ > 100000)
break;
}
if ((iCopy + 1) % 200 == 0) // By the way, what does your sendMessage(list[0]['1']); mean? what is this '1'? if it is i you are not thread safe.
Console.WriteLine(iCopy + " - Time elapsed: (ms)" + stopwatch.ElapsedMilliseconds);
});
}
Console.ReadKey();
Console.WriteLine("Memory usage: " + (GC.GetTotalMemory(false) - initialMemoryFootPrint));
Console.ReadKey();
}
Result:
So we can see that:
+--------+------------+------------+--------+
| | new Thread | ThreadPool | TPL |
+--------+------------+------------+--------+
| Time | 6749 | 228ms | 222ms |
| Memory | ≈300kb | ≈103kb | ≈123kb |
+--------+------------+------------+--------+
The above falls nicely inline to what we anticipated in theory. High memory for new Thread as well as slower overall performance when compared to ThreadPool. ThreadPool and TPL have equivalent performance with TPL having a slightly higher memory footprint than a pure thread pool but it's probably a price worth paying given the added flexibility Tasks provide (such as cancellation, waiting for completion querying status of task)
At this point, we have proven that using ThreadPool threads is the preferable option in terms of speed and memory.
Still, we have not answered your question. How to track the state of the threads running.
To answer your question
Given the insights we have gathered, this is how I would approach it:
List<string>[] list = listdbConnect.Select()
int itemCount = list[0].Count;
Task[] tasks = new Task[itemCount];
stopwatch.Start();
for (int i = 0; i < itemCount; i++)
{
tasks[i] = Task.Factory.StartNew(() =>
{
// NOTE: Do not use i in here as it is not thread safe to do so!
sendMessage(list[0]['1']);
//calling callback function
});
}
// if required you can wait for all tasks to complete
Task.WaitAll(tasks);
// or for any task you can check its state with properties such as:
tasks[1].IsCanceled
tasks[1].IsCompleted
tasks[1].IsFaulted
tasks[1].Status
As a final note, you can not use the variable i in your Thread.Start, since it would create a closure over a changing variable which would effectively be shared amongst all Threads. To get around this (assuming you need to access i), simply create a copy of the variable and pass the copy in, this would make one closure per thread which would make it thread safe.
Good luck!
Use Process.Threads:
var currentProcess = Process.GetCurrentProcess();
var threads = currentProcess.Threads;
Note: any threads owned by the current process will show up here, including those not explicitly created by you.
If you only want the threads that you created, well, why don't you just keep track of them when you create them?
Create a List<Thread> and store each new thread in your first for loop in it.
List<string>[] list;
List<Thread> threads = new List<Thread>();
list = dbConnect.Select();
for (int i = 0; i < list[0].Count; i++)
{
Thread th = new Thread(() =>{
sendMessage(list[0]['1']);
//calling callback function
});
th.Name = "SID"+i;
th.Start();
threads.add(th)
}
for (int i = 0; i < list[0].Count; i++)
{
threads[i].DoStuff()
}
However if you don't need i you can make the second loop a foreach instead of a for
As a side note, if your sendMessage function does not take very long to execute you should somthing lighter weight then a full Thread, use a ThreadPool.QueueUserWorkItem or if it is available to you, a Task
Process.GetCurrentProcess().Threads
This gives you a list of all threads running in the current process, but beware that there are threads other than those you started yourself.
Use Process.Threads to iterate through your threads.
Related
Are there more tasks being performed than threads? What's happening?
I wrote a simple code. The machine has 32 threads. At the twentieth second, I see the number 54 in the console. This means that 54 tasks have started. Each task uses thread suspension. I don't understand why tasks continue to run if tasks have already been created and started in all possible threads and the thread suspension code is running in each task. What's going on, how does it work? void MyMethod(int i) { Console.WriteLine(i); Thread.Sleep(int.MaxValue); } Console.WriteLine(Environment.ProcessorCount); for (int i = 0; i < int.MaxValue; i++) { Thread.Sleep(50); int j = i; Task.Run(() => MyMethod(j)); } And why does this code create so many tasks? (Environment.ProcessorCount => 32) using System.Net; void MyMethod(int i) { Console.WriteLine(WebRequest.Create("https://192.168.1.1").GetResponse().ContentLength); } for (int i = 0; i < Environment.ProcessorCount; i++) { int j = i; Task.Run(() => MyMethod(j)); } Thread.Sleep(int.MaxValue);
The Task.Run method runs the code on the ThreadPool, and the ThreadPool creates more threads when it becomes saturated. Initially it creates immediately on demand as many threads as the number of cores. After that point it is said to be saturated, and creates one new thread every second until the demand is satisfied. This rate is not documented. It is found by experimentation on .NET 6, and might change in future .NET versions. You are able to control the saturation threshold with the ThreadPool.SetMinThreads method. For example ThreadPool.SetMinThreads(100, 100). If you give it too large values, this method does nothing and returns false.
Thread vs Parallel.For performance
I am struggling to understand the difference between threads and Parallel.For. I created two functions, one used Parallel.For other invoked threads. Invoking 10 threads would appear to be faster, can anyone please explain? Would threads use multiple processors available in the system (to get executed in parallel) or does it just do time slicing in reference to CLR? public static bool ParallelProcess() { Stopwatch sw = new Stopwatch(); sw.Start(); Parallel.For(0, 10, x => { Console.WriteLine(string.Format("Printing {0} thread = {1}", x, Thread.CurrentThread.ManagedThreadId)); Thread.Sleep(3000); }); sw.Stop(); Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.Seconds)); return true; } public static bool ParallelThread() { Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 10; i++) { Thread t = new Thread(new ThreadStart(Thread1)); t.Start(); if (i == 9) t.Join(); } sw.Stop(); Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.Seconds)); return true; } private static void Thread1() { Console.WriteLine(string.Format("Printing {0} thread = {1}", 0, Thread.CurrentThread.ManagedThreadId)); Thread.Sleep(3000); } When called below methods, Parallel.For took twice time then threads. Algo.ParallelThread(); //took 3 secs Algo.ParallelProcess(); //took 6 secs
Parallel utilizes however many threads the underlying scheduler provides, which would be the minimum number of threadpool threads to start with. The number of minimum threadpool threads is by default set to the number of processors. As time goes on and based on many different factors, e.g. all current threads being busy, the scheduler might decide to spawn more threads and go higher than the minimum count. All of that is managed for you to stop unnecessary resource usage. Your second example circumvents all that by spawning threads manually. If you explicitly set the number of threadpool threads e.g. ThreadPool.SetMinThreads(100, 100), you'll see even the Parallel one takes 3 seconds as it immediately has more threads available to use.
You've got a bunch of things here that are going wrong. (1) Don't use sw.Elapsed.Seconds this value is an int and (obviously) truncates the fractional part of the time. Worse though, if you have a process that takes 61 seconds to complete this will report 1 as it's like the second hand on a clock. You should instead use sw.Elapsed.TotalSeconds which reports as a double and it shows the total number of seconds regardless how many minutes or hours, etc. (2) Parallel.For uses the thread-pool. This significantly reduces (or even eliminates) the overhead for creating threads. Each time you call new Thread(() => ...) you are allocating over 1MB of RAM and chewing up valuable resources before any processing can take place. (3) You're artificially loading up the threads with Thread.Sleep(3000); and this means you are overshadowing the actual time it takes to create threads with a massive sleep. (4) Parallel.For is, by default, limited by the number of cores on your CPU. So when you run 10 threads the work is being cut in to two steps - meaning that the Thread.Sleep(3000); is being run twice in series, hence the 6 seconds that it's running. The new Thread approach is running all of the threads in one go meaning that it takes just over 3 seconds, but again, the Thread.Sleep(3000); is swamping the thread start up time. (5) You're also dealing with a CLR JIT issue. The first time you run your code the start-up costs are enormous. Let's change the code to remove the sleeps and to properly join the threads: public static bool ParallelProcess() { Stopwatch sw = new Stopwatch(); sw.Start(); Parallel.For(0, 10, x => { Console.WriteLine(string.Format("Printing {0} thread = {1}", x, Thread.CurrentThread.ManagedThreadId)); }); sw.Stop(); Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.TotalMilliseconds)); return true; } public static bool ParallelThread() { Stopwatch sw = new Stopwatch(); sw.Start(); var threads = Enumerable.Range(0, 10).Select(x => new Thread(new ThreadStart(Thread1))).ToList(); foreach (var thread in threads) thread.Start(); foreach (var thread in threads) thread.Join(); sw.Stop(); Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.TotalMilliseconds)); return true; } private static void Thread1() { Console.WriteLine(string.Format("Printing {0} thread = {1}", 0, Thread.CurrentThread.ManagedThreadId)); } Now, to get rid of the CLR/JIT start up time, let's run the code like this: ParallelProcess(); ParallelThread(); ParallelProcess(); ParallelThread(); ParallelProcess(); ParallelThread(); The times we get are like this: Time in secs 3.8617 Time in secs 4.7719 Time in secs 0.3633 Time in secs 1.6332 Time in secs 0.3551 Time in secs 1.6148 The starting run times are terrible compared to the second and third runs that are far more consistent. The result is that running Parallel.For is 4 to 5 times faster than calling new Thread.
Your snippets are not equivalent. Here is a version of ParallelThread that would do the same as ParallelProcess but starting new threads: public static bool ParallelThread() { Stopwatch sw = new Stopwatch(); sw.Start(); var threads = new Thread[10]; for (int i = 0; i < 10; i++) { int x = i; threads[i] = new Thread(() => Thread1(x)); threads[i].Start(); } for (int i = 0; i < 10; i++) { threads[i].Join(); } sw.Stop(); Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.Seconds)); return true; } private static void Thread1(int x) { Console.WriteLine(string.Format("Printing {0} thread = {1}", x, Thread.CurrentThread.ManagedThreadId)); Thread.Sleep(3000); } Here, I am making sure to wait for all the threads. And also, I making sure to match the console output. Things that OP code does not do. However, the time difference is still there. Let me tell you what makes the difference, at least in my tests: the order. Run ParallelProcess before ParallelThread and they should both take 3 seconds to complete (ignoring the initial runs, which will take longer because of compilation). I cannot really explain it. We could modify the above code futher to use the ThreadPool, and that did also result in ParallelProcess completing in 3 seconds (even though I did not modify that version). This is the version of ParallelThread with ThreadPool I came up with: public static bool ParallelThread() { Stopwatch sw = new Stopwatch(); sw.Start(); var events = new ManualResetEvent[10]; for (int i = 0; i < 10; i++) { int x = i; events[x] = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem ( _ => { Thread1(x); events[x].Set(); } ); } for (int i = 0; i < 10; i++) { events[i].WaitOne(); } sw.Stop(); Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.Seconds)); return true; } private static void Thread1(int x) { Console.WriteLine(string.Format("Printing {0} thread = {1}", x, Thread.CurrentThread.ManagedThreadId)); Thread.Sleep(3000); } Note: We could use WaitAll on the events, but that would fail on a STAThread. You have Thread.Sleep(3000) which are the 3 seconds we see. Meaning that we are not really measuring the overhead of any of these methods. So, I decided I want to study this futher, and to do it, I went up one order of magnitud (from 10 to 100) and removed the Console.WriteLine (which is introducing synchronization anyway). This is my code listing: void Main() { ParallelThread(); ParallelProcess(); } public static bool ParallelProcess() { Stopwatch sw = new Stopwatch(); sw.Start(); Parallel.For(0, 100, x => { /*Console.WriteLine(string.Format("Printing {0} thread = {1}", x, Thread.CurrentThread.ManagedThreadId));*/ Thread.Sleep(3000); }); sw.Stop(); Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.Seconds)); return true; } public static bool ParallelThread() { Stopwatch sw = new Stopwatch(); sw.Start(); var events = new ManualResetEvent[100]; for (int i = 0; i < 100; i++) { int x = i; events[x] = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem ( _ => { Thread1(x); events[x].Set(); } ); } for (int i = 0; i < 100; i++) { events[i].WaitOne(); } sw.Stop(); Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.Seconds)); return true; } private static void Thread1(int x) { /*Console.WriteLine(string.Format("Printing {0} thread = {1}", x, Thread.CurrentThread.ManagedThreadId));*/ Thread.Sleep(3000); } I am getting 6 seconds for ParallelThread and 9 seconds for ParallelProcess. This remains true even after reversing the order. Which makes me much more confident that this is a real measure of the overhead. Adding ThreadPool.SetMinThreads(100, 100); bring the time back down to 3 seconds, for both ParallelThread (remember that this version is using the ThreadPool) and ParallelProcess. Meaning that this overhead comes from the thread pool. Now, I can go back to the version that spawns new threads (modified to spawn 100 and with Console.WriteLine commented): public static bool ParallelThread() { Stopwatch sw = new Stopwatch(); sw.Start(); var threads = new Thread[100]; for (int i = 0; i < 100; i++) { int x = i; threads[i] = new Thread(() => Thread1(x)); threads[i].Start(); } for (int i = 0; i < 100; i++) { threads[i].Join(); } sw.Stop(); Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.Seconds)); return true; } private static void Thread1(int x) { /*Console.WriteLine(string.Format("Printing {0} thread = {1}", x, Thread.CurrentThread.ManagedThreadId));*/ Thread.Sleep(3000); } I get consistent 3 seconds from this version (meaning the time overhead is negligible, since, as I said earlier, Thread.Sleep(3000) is 3 seconds), however I want to note that it would be leaving more garbage to collect than using the ThreadPool or Parallel.For. On the other hand, using Parallel.For remains tied to the ThreadPool. By the way, if you want to degrade its performance, reducing the minimun number of threads is not enough, you got to degreade the maximun number of threads too (e.g. ThreadPool.SetMaxThreads(1, 1);). All in all, please notice that Parallel.For is easier to use, and harder to wrong. Invoking 10 threads would appear to be faster, can anyone please explain? Spawning threads is fast. Although, it will leade to more garbage. Also, note that your test is not great. Would threads use multiple processors available in the system (to get executed in parallel) or does it just do time slicing in reference to CLR? Yes, they would. They map to the underlaying operating system threads, can be preempted by it, and will run in any core according to their affinity (see ProcessThread.ProcessorAffinity). To be clear, they are not fibers nor coroutines.
To put it in the simplest of the simplest terms, using Thread class guarantees to create a thread on the operating system level but using the Parallel.For the CLR thinks twice before spawning the OS-level threads. If it feels that it is a good time to create thread on OS-level, it goes ahead, otherwise it employs the available Thread pool. TPL is written to be optimized with a multi-core environment.
C# Wait for signals from all the threads before proceed
I'm writing a C# program which involves multithreading and synchronization between multiple threads. The threads all need perform some iterative work independently, and after some thread has finished a specified number of iterations, it must wait for the other threads to come up. After all of them have finished given number of iterations and obtained some intermediate result, they should do some synchronized work and then continue execution again, until another synchronization point is reached and so on. Here's my attempt to achieve this (a thread should pause after just one iteration, then wait for the others): int nThreads = Environment.ProcessorCount; Thread[] threads = new Thread[nThreads]; ManualResetEvent[] manualResetEvents = new ManualResetEvent[nThreads]; for (int i = 0; i < nThreads; i++) { manualResetEvents[i] = new ManualResetEvent(false); } int nSteps = 5; Random rnd = new Random(); for (int i = 0; i < nThreads; i++) { int idx = i; threads[i] = new Thread(delegate () { int cStep = nSteps; while (cStep > 0) { manualResetEvents[idx].Reset(); Console.Write("\nThread {0} working... cStep = {1}\n", idx, cStep); Thread.Sleep(rnd.Next(1000)); manualResetEvents[idx].Set(); Console.WriteLine("\nThread {0} work done. Waiting Others...cStep = {1}\n", idx, cStep); WaitHandle.WaitAll(manualResetEvents); cStep--; } }); } for (int i = 0; i < nThreads; i++) { threads[i].Start(); } for (int i = 0; i < nThreads; i++) { threads[i].Join(); } But the code above appears not working, for not any thread waits for all of the other threads to perform one iteration for some reason. I think I misunderstand the purpose of ManualResetEvent or use it the wrong way, what could you suggest?
Your code is prone to race conditions. After all threads have completed the first iteration, all events are still set; if a single thread then runs through the loop before the others get to reset their events, it'll see the other events still set, and stop waiting early. There's plenty of ways to resolve this bug, but the best solution for you is System.Threading.Barrier (also see Threading objects and features with section about Barrier). It's explicitly designed for this situation, where you want multiple threads to work in parallel through a multi-step algorithm.
Suggest a way in threading that always fixed number of threads must be used in computing?
I have an array of filepath in List<string> with thousands of files. I want to process them in a function parallel with 8 threads. ParallelOptions opt= new ParallelOptions(); opt.TaskScheduler = null; opt.MaxDegreeOfParallelism = 8; Parallel.ForEach(fileList, opt, item => DoSomething(item)); This code works fine for me but it guarantees to run max 8 threads and I want to run 8 threads always. CLR decides the number of threads to be use as per CPU load. Please suggest a way in threading that always 8 threads are used in computing with minimum overhead.
Use a producer / consumer model. Create one producer and 8 consumers. For example: BlockingCollection<string> _filesToProcess = new BlockingCollection<string>(); // start 8 tasks to do the processing List<Task> _consumers = new List<Task>(); for (int i = 0; i < 8; ++i) { var t = Task.Factory.StartNew(ProcessFiles, TaskCreationOptions.LongRunning); _consumers.Add(t); } // Populate the queue foreach (var filename in filelist) { _filesToProcess.Add(filename); } // Mark the collection as complete for adding _filesToProcess.CompleteAdding(); // wait for consumers to finish Task.WaitAll(_consumers.ToArray(), Timeout.Infinite); Your processing method removes things from the BlockingCollection and processes them: void ProcessFiles() { foreach (var filename in _filesToProcess.GetConsumingEnumerable()) { // do something with the file name } } That will keep 8 threads running until the collection is empty. Assuming, of course, you have 8 cores on which to run the threads. If you have fewer available cores, then there will be a lot of context switching, which will cost you. See BlockingCollection for more information.
Within a static counter, you might be able to get the number of current threads. Every time you call start a task there is the possibility to use the Task.ContinueWith (http://msdn.microsoft.com/en-us/library/dd270696.aspx) to notify that it's over and you can start another one. This way there is going to be always 8 tasks running.
OrderablePartitioner<Tuple<int, int>> chunkPart = Partitioner.Create(0, fileList.Count, 1);//Partition the list in chunk of 1 entry ParallelOptions opt= new ParallelOptions(); opt.TaskScheduler = null; opt.MaxDegreeOfParallelism = 8; Parallel.ForEach(chunkPart, opt, chunkRange => { for (int i = chunkRange.Item1; i < chunkRange.Item2; i++) { DoSomething(fileList[i].FullName); } });
Why does thread priority have no effect?
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...