I am new in Threads.
And wanted to write a simple program with threads in C#.
The goal was when I press any key it must create new thread,
and every thread must write count which increments it's value every time,
when new thread was created. But result was not what expected :).
It first waits for keypress and after keypress it writes only 111111111111111.... It does not write 2, 3 ,4 and etc. So what is the problem? How can I solve it?
The expected result was like that:
11112222333311112222333344441111...
The code is below.
class Program
{
static Thread t;
static int count = 1;
static void Main(string[] args)
{
Console.Title = "Thread Test";
t = new Thread(wait);
t.Start();
Console.WriteLine("Main Thread End...");
}
static void write(object o)
{
while(true)
{
Console.Write(o.ToString());
Thread.Sleep(500);
}
}
static void wait()
{
Console.ReadKey();
Thread tt = new Thread(write);
tt.Start(count);
count++;
}
}
Perhaps a recursive wait() method is what you want?
static void wait()
{
Console.ReadKey();
Thread tt = new Thread(write);
tt.Start(count);
count++;
wait(); //Added
}
Try this sample :-)
You can try to create more different tasks with different priority.
In the write() method you can printing the name of current task, if you want storage in class more different value you can add property through inheritance
class Program
{
static List<Thread> lst = new List<Thread>();
//static Thread t;
static int count = 1;
static void Main(string[] args)
{
System.Console.Title = "Thread Test";
createThread();
foreach (Thread t in lst) t.Start();
//System.Console.WriteLine("Main Thread End...");
}
static void write()
{
while (true)
{
System.Console.Write(Thread.CurrentThread.Name);
Thread.Sleep(500);
}
}
static void createThread()
{
Random rnd = new Random();
while (count<=5)
{
Thread tt = new Thread(write);
if (rnd.Next(0,10)>=5)
{
tt.Priority = ThreadPriority.Highest;
}
else
{
tt.Priority = ThreadPriority.Lowest;
}
tt.Name = count.ToString();
lst.Add(tt);
count++;
}
}
}
Related
As being a newbie with doing threads and tasks, I wrote two threads and one task in my little practice application as below:
static List<string> myList = new List<string>();
static void Main(string[] args)
{
//Run the whole operation both threads and task.
Operation();
}
static async void Operation()
{
Task t = Task.Run(new Action(RunThreads));
t.Wait();
//Write the result.
WriteMessage();
}
static void RunThreads()
{
//Read thread1.
string threadName = "Thread-1";
Thread thread1 = new Thread(() => DoSomething(threadName));
thread1.Name = threadName;
thread1.Start();
//Read thread2.
threadName = "Thread-2";
Thread thread2 = new Thread(() => DoSomething(threadName));
thread2.Name = threadName;
thread2.Start();
}
public static void DoSomething(string threadName)
{
for (int i = 1; i < 10; i++)
{
myList.Add(string.Format("{0} from thread: {1}", i, threadName));
}
}
private static void WriteMessage()
{
foreach (string val in myList)
{
Console.WriteLine(val);
}
Console.Read();
}
I want both threads to be first entirely executed and the values are added in "myList". Once those threads are completed (Eventually by the end of those two threads, "myList" will contain 20 items...) then run the "WriteMessage()" method to loop through all those 20 items and print them in the console.
Below is the output that I am expecting to be written in the console:
1 from thread: Thread-2
1 from thread: Thread-1
2 from thread: Thread-1
2 from thread: Thread-2
3 from thread: Thread-2
4 from thread: Thread-2
3 from thread: Thread-1
5 from thread: Thread-2
This list continues upto 20 items.
(I know that the sequence of messages from "Thread-1" and "Thread-2" may differ because the process will be asynchronous but there should be exactly 10 item for each).
The issue with my implementation is: The WriteMessage() method is being executed before those two threads are completed.
What I think you are trying to do is make the Operation void wait until the two other threads are completed. What I have done is created a boolean that will turn true when the threads are done, therefore letting the Operation continue. This worked for VS2017. On line 2 you can see the bool, line 17 is where it waits, and line 33 is where the boolean is changed. Im currently not on my desktop (laptop, verry slow) so if you are having further problems I can modify this answer.
static List<string> myList = new List<string>();
static bool taskDone = false;
static void Main(string[] args)
{
//Run the whole operation both threads and task.
Operation();
}
static async void Operation()
{
Task t = Task.Run(new Action(RunThreads));
t.Wait();
//Write the result.
while(!taskDone);
WriteMessage();
}
static void RunThreads()
{
//Read thread1.
string threadName = "Thread-1";
Thread thread1 = new Thread(() => DoSomething(threadName));
thread1.Name = threadName;
thread1.Start();
//Read thread2.
threadName = "Thread-2";
Thread thread2 = new Thread(() => DoSomething(threadName));
thread2.Name = threadName;
thread2.Start();
taskDone = true;
}
public static void DoSomething(string threadName)
{
for (int i = 1; i < 10; i++)
{
myList.Add(string.Format("{0} from thread: {1}", i, threadName));
}
}
private static void WriteMessage()
{
foreach (string val in myList)
{
Console.WriteLine(val);
}
Console.Read();
}
You can use Task for implementing this. Find the code provided below. Arguments passed to the DoWork function are the parameters to execute the work. This should be dynamically set from the loop for each DoWork call.
int numberOfProcess = 3;
Task[] _tasks = new Task[numberOfProcess];
for (int i = 1; i <= numberOfProcess; i++)
{
string[] args = new string[2];
args[0] = minSlNo.ToString();
args[1] = nextSlno.ToString();
_tasks[i - 1] = Task.Factory.StartNew(() =>
{
//do the required work
DoWork(args);
});
System.Console.WriteLine("Min =" + minSlNo + " Next Msg=" + nextSlno);
SetLogFilesProperty("BatchJob_Start", args[0].ToString() + "_" + args[1].ToString());
}
while (_tasks.Any(t => !t.IsCompleted))
{//execution waits till all the tasks are completed
}
Console.Write("All Tasks Completed"+DateTime.Now);
static object _lock = new object();
static List<string> myList = new List<string>();
TaskFactory TaskFac = new TaskFactory();
static void Main(string[] args)
{
//Run the whole operation both threads and task.
Operation();
}
static async void Operation()
{
Task t = Task.Run(new Action(RunThreads)).ContinueWith(o => {
WriteMessage();
});
t.Wait();
Console.ReadKey();
//Write the result.
// WriteMessage();
}
static void RunThreads()
{
//Read thread1.
string threadName = "Thread-1";
Thread thread1 = new Thread(() =>
{
for (int i = 1; i < 11; i++)
{
DoSomething(
threadName, i
);
}
});
thread1.Start();
string threadName1 = "Thread-2";
Thread thread2 = new Thread(() => {
for (int i = 1; i < 11; i++)
{
DoSomething(
threadName1, i
);
} });
thread2.Start();
}
public static void DoSomething(string threadName,int loop_index)
{
Monitor.Enter(_lock);
{
myList.Add(string.Format("{0} from thread: {1}",loop_index, threadName));
Monitor.Exit(_lock);
}
}
private static void WriteMessage()
{
foreach (string val in myList)
{
Console.WriteLine(val);
}
Console.Read();
}
I am exploring with the concept of starting a thread within another thread. this is the code I have come up with, this is watered down version of another program which I am developing currently however I found out that the second level of threads do not complete successfully.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication4
{
public class SomeClassA
{
public SomeClassA(string display)
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine(display);
}
}
public class MainSomeClassA
{
public List<SomeClassA> SomeClassaAList;
public List<Thread> ThreadList;
public MainSomeClassA()
{
ThreadList = new List<Thread>();
SomeClassaAList = new List<SomeClassA>();
for (int i = 0; i < 10; i++)
{
ThreadList.Add(new Thread(() => StartThread("Hello")));
}
WaitComplete();
}
public void WaitComplete()
{
bool AllThreadsAlive = true;
while (AllThreadsAlive)
{
AllThreadsAlive = false;
foreach (Thread t in ThreadList)
{
if (t.IsAlive)
{
AllThreadsAlive = true;
}
}
}
}
public void StartThread(string display)
{
SomeClassaAList.Add(new SomeClassA(display));
}
}
class Program
{
public static List<MainSomeClassA> MainSomeClassAList = new List<MainSomeClassA>();
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
MainSomeClassAList = new List<MainSomeClassA>();
List<Thread> ThreadList = new List<Thread>();
bool threadsAlive = true;
sw.Reset();
sw.Start();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(AddToMainClassAList);
t.Start();
ThreadList.Add(t);
}
while (threadsAlive)
{
threadsAlive = false;
foreach (Thread t in ThreadList)
{
if (t.IsAlive)
{
threadsAlive = true;
}
}
}
sw.Stop();
Console.WriteLine("Elapsed Time: {0}", sw.ElapsedMilliseconds);
Console.ReadKey();
}
public static void AddToMainClassAList()
{
MainSomeClassAList.Add(new MainSomeClassA());
}
}
}
The above code does not print out "hello" and exits without creating the SomeClassA List.
The problem with your code is that you never start the inner threads. Change you constructor to look like this, and it will work:
public MainSomeClassA()
{
ThreadList = new List<Thread>();
SomeClassaAList = new List<SomeClassA>();
for (int i = 0; i < 10; i++)
{
ThreadList.Add(new Thread(() => StartThread("Hello")));
// Start thread here:
ThreadList[ThreadList.Count - 1].Start();
}
WaitComplete();
}
That said, I should point out that you're lucky the program doesn't crash. You have ten threads concurrently trying to modify the MainSomeClassAList object, some of which will necessarily force a reallocation of the internal buffer. As it is, if you print out the Count of the list at the end, you will find it isn't always 10 as it ought to be.
For the code to be truly correct, you would need to add synchronization around the call to Add() in the AddToMainClassAList() method. Same thing applies to the StartThread() method and the SomeClassaAList object.
Finally, your method for waiting on the threads is very poor. You should try to avoid polling at all costs. In this case, the Thread.Join() method is a reasonable choice (you should try to avoid blocking a thread at all, but for this example, it's unavoidable). For example, your busy loop can be replaced by this:
foreach (Thread thread in ThreadList)
{
thread.Join();
}
I have some code that runs thousands of URLs through a third party library. Occasionally the method in the library hangs which takes up a thread. After a while all threads are taken up by processes doing nothing and it grinds to a halt.
I am using a SemaphoreSlim to control adding new threads so I can have an optimal number of tasks running. I need a way to identify tasks that have been running too long and then to kill them but also release a thread from the SemaphoreSlim so a new task can be created.
I am struggling with the approach here so I made some test code that immitates what I am doing. It create tasks that have a 10% chance of hanging so very quickly all threads have hung.
How should I be checking for these and killing them off?
Here is the code:
class Program
{
public static SemaphoreSlim semaphore;
public static List<Task> taskList;
static void Main(string[] args)
{
List<string> urlList = new List<string>();
Console.WriteLine("Generating list");
for (int i = 0; i < 1000; i++)
{
//adding random strings to simulate a large list of URLs to process
urlList.Add(Path.GetRandomFileName());
}
Console.WriteLine("Queueing tasks");
semaphore = new SemaphoreSlim(10, 10);
Task.Run(() => QueueTasks(urlList));
Console.ReadLine();
}
static void QueueTasks(List<string> urlList)
{
taskList = new List<Task>();
foreach (var url in urlList)
{
Console.WriteLine("{0} tasks can enter the semaphore.",
semaphore.CurrentCount);
semaphore.Wait();
taskList.Add(DoTheThing(url));
}
}
static async Task DoTheThing(string url)
{
Random rand = new Random();
// simulate the IO process
await Task.Delay(rand.Next(2000, 10000));
// add a 10% chance that the thread will hang simulating what happens occasionally with http request
int chance = rand.Next(1, 100);
if (chance <= 10)
{
while (true)
{
await Task.Delay(1000000);
}
}
semaphore.Release();
Console.WriteLine(url);
}
}
As people have already pointed out, Aborting threads in general is bad and there is no guaranteed way of doing it in C#. Using a separate process to do the work and then kill it is a slightly better idea than attempting Thread.Abort; but still not the best way to go. Ideally, you want co-operative threads/processes, which use IPC to decide when to bail out themselves. This way the cleanup is done properly.
With all that said, you can use code like below to do what you intend to do. I have written it assuming your task will be done in a thread. With slight changes, you can use the same logic to do your task in a process
The code is by no means bullet-proof and is meant to be illustrative. The concurrent code is not really tested well. Locks are held for longer than needed and some places I am not locking (like the Log function)
class TaskInfo {
public Thread Task;
public DateTime StartTime;
public TaskInfo(ParameterizedThreadStart startInfo, object startArg) {
Task = new Thread(startInfo);
Task.Start(startArg);
StartTime = DateTime.Now;
}
}
class Program {
const int MAX_THREADS = 1;
const int TASK_TIMEOUT = 6; // in seconds
const int CLEANUP_INTERVAL = TASK_TIMEOUT; // in seconds
public static SemaphoreSlim semaphore;
public static List<TaskInfo> TaskList;
public static object TaskListLock = new object();
public static Timer CleanupTimer;
static void Main(string[] args) {
List<string> urlList = new List<string>();
Log("Generating list");
for (int i = 0; i < 2; i++) {
//adding random strings to simulate a large list of URLs to process
urlList.Add(Path.GetRandomFileName());
}
Log("Queueing tasks");
semaphore = new SemaphoreSlim(MAX_THREADS, MAX_THREADS);
Task.Run(() => QueueTasks(urlList));
CleanupTimer = new Timer(CleanupTasks, null, CLEANUP_INTERVAL * 1000, CLEANUP_INTERVAL * 1000);
Console.ReadLine();
}
// TODO: Guard against re-entrancy
static void CleanupTasks(object state) {
Log("CleanupTasks started");
lock (TaskListLock) {
var now = DateTime.Now;
int n = TaskList.Count;
for (int i = n - 1; i >= 0; --i) {
var task = TaskList[i];
Log($"Checking task with ID {task.Task.ManagedThreadId}");
// kill processes running for longer than anticipated
if (task.Task.IsAlive && now.Subtract(task.StartTime).TotalSeconds >= TASK_TIMEOUT) {
Log("Cleaning up hung task");
task.Task.Abort();
}
// remove task if it is not alive
if (!task.Task.IsAlive) {
Log("Removing dead task from list");
TaskList.RemoveAt(i);
continue;
}
}
if (TaskList.Count == 0) {
Log("Disposing cleanup thread");
CleanupTimer.Dispose();
}
}
Log("CleanupTasks done");
}
static void QueueTasks(List<string> urlList) {
TaskList = new List<TaskInfo>();
foreach (var url in urlList) {
Log($"Trying to schedule url = {url}");
semaphore.Wait();
Log("Semaphore acquired");
ParameterizedThreadStart taskRoutine = obj => {
try {
DoTheThing((string)obj);
} finally {
Log("Releasing semaphore");
semaphore.Release();
}
};
var task = new TaskInfo(taskRoutine, url);
lock (TaskListLock)
TaskList.Add(task);
}
Log("All tasks queued");
}
// simulate all processes get hung
static void DoTheThing(string url) {
while (true)
Thread.Sleep(5000);
}
static void Log(string msg) {
Console.WriteLine("{0:HH:mm:ss.fff} Thread {1,2} {2}", DateTime.Now, Thread.CurrentThread.ManagedThreadId.ToString(), msg);
}
}
I have following code which throws SemaphoreFullException, I don't understand why ?
If I change _semaphore = new SemaphoreSlim(0, 2) to
_semaphore = new SemaphoreSlim(0, int.MaxValue)
then all works fine.
Can anyone please find fault with this code and explain to me.
class BlockingQueue<T>
{
private Queue<T> _queue = new Queue<T>();
private SemaphoreSlim _semaphore = new SemaphoreSlim(0, 2);
public void Enqueue(T data)
{
if (data == null) throw new ArgumentNullException("data");
lock (_queue)
{
_queue.Enqueue(data);
}
_semaphore.Release();
}
public T Dequeue()
{
_semaphore.Wait();
lock (_queue)
{
return _queue.Dequeue();
}
}
}
public class Test
{
private static BlockingQueue<string> _bq = new BlockingQueue<string>();
public static void Main()
{
for (int i = 0; i < 100; i++)
{
_bq.Enqueue("item-" + i);
}
for (int i = 0; i < 5; i++)
{
Thread t = new Thread(Produce);
t.Start();
}
for (int i = 0; i < 100; i++)
{
Thread t = new Thread(Consume);
t.Start();
}
Console.ReadLine();
}
private static Random _random = new Random();
private static void Produce()
{
while (true)
{
_bq.Enqueue("item-" + _random.Next());
Thread.Sleep(2000);
}
}
private static void Consume()
{
while (true)
{
Console.WriteLine("Consumed-" + _bq.Dequeue());
Thread.Sleep(1000);
}
}
}
If you want to use the semaphore to control the number of concurrent threads, you're using it wrong. You should acquire the semaphore when you dequeue an item, and release the semaphore when the thread is done processing that item.
What you have right now is a system that allows only two items to be in the queue at any one time. Initially, your semaphore has a count of 2. Each time you enqueue an item, the count is reduced. After two items, the count is 0 and if you try to release again you're going to get a semaphore full exception.
If you really want to do this with a semaphore, you need to remove the Release call from the Enqueue method. And add a Release method to the BlockingQueue class. You then would write:
private static void Consume()
{
while (true)
{
Console.WriteLine("Consumed-" + _bq.Dequeue());
Thread.Sleep(1000);
bq.Release();
}
}
That would make your code work, but it's not a very good solution. A much better solution would be to use BlockingCollection<T> and two persistent consumers. Something like:
private BlockingCollection<int> bq = new BlockingCollection<int>();
void Test()
{
// create two consumers
var c1 = new Thread(Consume);
var c2 = new Thread(Consume);
c1.Start();
c2.Start();
// produce
for (var i = 0; i < 100; ++i)
{
bq.Add(i);
}
bq.CompleteAdding();
c1.Join();
c2.Join();
}
void Consume()
{
foreach (var i in bq.GetConsumingEnumerable())
{
Console.WriteLine("Consumed-" + i);
Thread.Sleep(1000);
}
}
That gives you two persistent threads consuming the items. The benefit is that you avoid the cost of spinning up a new thread (or having the RTL assign a pool thread) for each item. Instead, the threads do non-busy waits on the queue. You also don't have to worry about explicit locking, etc. The code is simpler, more robust, and much less likely to contain a bug.
I have three threads in my program and I want that when thread one finishes it signals thread 2 to start and when thread 2 finishes it should signal thread 3 to start.
How can I achieve this, I know there are wait handles to do that in C#, but I don't know how to use them ?
Following is the code of my program:
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(Task1);
Thread t2 = new Thread(Task2);
Thread t3 = new Thread(Task3);
t1.Start();
t2.Start();
t3.Start();
Console.Read();
}
public static void Task1()
{
Console.WriteLine("I am assigned task 1:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task1" );
}
}
public static void Task2()
{
Console.WriteLine("I am assigned task 2:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task2");
}
}
public static void Task3()
{
Console.WriteLine("I am assigned task 3:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task3");
}
}
}
You need to pass events into the threaded functions that indicate what to signal when each one has finished and what to wait on before they run. Take a look at the (untested) code below to see what I mean:
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(Task1);
ManualResetEvent e1=new ManualResetEvent(false);
Thread t2 = new Thread(Task2);
ManualResetEvent e2=new ManualResetEvent(false);
Thread t3 = new Thread(Task3);
ManualResetEvent e3=new ManualResetEvent(false);
t1.Start(()=>Task1(e1));
t2.Start(()=>Task2(e1,e2));
t3.Start(()=>Task3(e2,e3);
Console.Read();
t1.Join();
t2.Join();
t3.Join();
}
public static void Task1(EventWaitHandle handle)
{
Console.WriteLine("I am assigned task 1:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task1" );
}
handle.Set();
}
public static void Task2(EventWaitHandle waitFor, EventWaitHandle handle)
{
waitFor.WaitOne();
Console.WriteLine("I am assigned task 2:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task2");
}
handle.Set();
}
public static void Task3(EventWaitHandle waitFor, EventWaitHandle handle)
{
waitFor.WaitOne();
Console.WriteLine("I am assigned task 3:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task3");
}
handle.Set();
}
}
It appears that you want to run Tasks 1 - 3 to execute synchronously. So, you might as well do:
Task1();
Task2();
Task3();
If you want to offload the execution of these tasks to another thread, you can do:
static void RunTasks()
{
Task1();
Task2();
Task3();
}
static void Main()
{
new Thread(RunTasks).Start();
}
If you really wanted each task to run on a separate thread, and wait for the previous task to finish, you can use the Thread.Join method.
EDIT:
Since you really want to use wait-handles to accomplish this, take a look at the ManualResetEvent class.
Notifies one or more waiting threads
that an event has occurred.
Call the WaitOne method on it to wait on the event, and the Set method to signal it.
Example (horribly contrived code):
var afterT1Event = new ManualResetEvent(false);
var afterT2Event = new ManualResetEvent(false);
Thread t1 = new Thread(() => { Task1(); afterT1Event.Set(); });
Thread t2 = new Thread(() => { afterT1Event.WaitOne(); Task2(); afterT2Event.Set(); });
Thread t3 = new Thread(() => { afterT2Event.WaitOne(); Task3(); });
t1.Start();
t2.Start();
t3.Start();
If you want to use WaitHandles to acheive these then you could do the following:
declare the following two fields:
static ManualResetEvent handle1 = new ManualResetEvent(false);
static ManualResetEvent handle2 = new ManualResetEvent(false);
then at the end of Task1, add this:
handle1.Set();
at the beginning of Task2, add:
handle1.WaitOne();
then at the end, add
handle2.Set();
then finally at the beginning of Task3 add
handle2.WaitOne();
This feels very artificial, almost like homework...
... but basically you can use Join on a thread to wait for it.
Or the old msdn tutorial/example is very reasonable on this: http://msdn.microsoft.com/en-us/library/aa645740(VS.71).aspx
You could use ManualResetEvents and WaitHandle.WaitAny. Basically when one thread is done you would notify the other thread by using a ManualResetEvent (ManualResetEvent.Set()).
ManualResetEvent threadFinished = new ManualResetEvent(false);
//You would set this in the thread that has finished
threadFinished.Set()
//You would use this in the thread that you want to wait for this event to be signalled
int nWait = WaitHandle.WaitAny(new ManualResetEvent[] { threadFinished }, 10, true);
//if yes stop thread
if (nWait == 0)
{
//Thread is finished
}
i think using thread.join() will be more simpler any other solution