I am trying to test a simply designed code piece on Microsoft HPC. It looks like the job is not completing the all code. My test method might be wrong though. I am just printing out some check points. Here is the code:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
class S
{
static void Main()
{
pcount = Environment.ProcessorCount;
Console.WriteLine("Proc count = " + pcount);
ThreadPool.SetMinThreads(4, -1);
ThreadPool.SetMaxThreads(4, -1);
// System.Threading.Thread.Sleep(20000);
Console.WriteLine("check point 0 ");
t1 = new Task(A, 1);
t2 = new Task(A, 2);
t3 = new Task(A, 3);
t4 = new Task(A, 4);
Console.WriteLine("Starting t1 " + t1.Id.ToString());
t1.Start();
Console.WriteLine("Starting t2 " + t2.Id.ToString());
t2.Start();
Console.WriteLine("Starting t3 " + t3.Id.ToString());
t3.Start();
Console.WriteLine("Starting t4 " + t4.Id.ToString());
t4.Start();
// Console.ReadLine();
}
static void A(object o)
{
Console.WriteLine("check point A ");
B(o);
}
static void B(object o)
{
int temp = (int)o;
Console.WriteLine("check point B ");
if (temp == 1)
{
C(o);
}
else
{
F(o);
}
}
static void C(object o)
{
Console.WriteLine("check point C ");
D(o);
}
static void D(object o)
{
int temp = (int)o;
Console.WriteLine("check point D " + temp);
if (temp == 2)
{
F(o);
}
else
{
E(o);
}
}
static void E(object o)
{
Console.WriteLine("check point E ");
}
static void F(object o)
{
Console.WriteLine("check point F ");
G(o);
}
static void G(object o)
{
Console.WriteLine("check point G ");
}
static Task t1, t2, t3, t4;
static int pcount;
}
In the job output, it is not printing till to the end. Printout ends randomly at any point( in a random function). Ok, I understand that, It may not able to print everything since the execution is faster than printing (possible explanation). But, if I try to place breakpoints and try to debug by attaching to process, it only hits the breakpoints in the first parts of the code. Looks like hitting the same range as test print out has. How I can make sure that the code runs through the end, so that breakpoints at any point can be hit?
A Task is designed to run on a so-called background thread. That means: If the main thread terminates, so will the background thread. So as soon as your Main() method completes, all threads (and therefore all Tasks) get terminated, and your program ends.
The solution is to wait for your Tasks to complete.
static void Main()
{
pcount = Environment.ProcessorCount;
Console.WriteLine("Proc count = " + pcount);
ThreadPool.SetMinThreads(4, -1);
ThreadPool.SetMaxThreads(4, -1);
// System.Threading.Thread.Sleep(20000);
Console.WriteLine("check point 0 ");
t1 = new Task(A, 1);
t2 = new Task(A, 2);
t3 = new Task(A, 3);
t4 = new Task(A, 4);
Console.WriteLine("Starting t1 " + t1.Id.ToString());
t1.Start();
Console.WriteLine("Starting t2 " + t2.Id.ToString());
t2.Start();
Console.WriteLine("Starting t3 " + t3.Id.ToString());
t3.Start();
Console.WriteLine("Starting t4 " + t4.Id.ToString());
t4.Start();
// Console.ReadLine();
t1.Wait();
t2.Wait();
t3.Wait();
t4.Wait();
}
Related
im new to C# and i was trying to figure out async and await . for practice i was trying to start method 1 in which method 2 is called twice . method 2 takes a value and increases it by 1 each 200 ms . instead of running method 2 the program ends after the first line of method 1 .
static void Main(string[] args)
{
Method1();
}
static int Method2(int x)
{
for (int i = 0; i < 10; i++)
{
x += 1;
Console.WriteLine(x);
Thread.Sleep(200);
}
Console.WriteLine("final" + " " + x + " " + Thread.CurrentThread.ManagedThreadId);
return x;
}
static async Task Method1()
{
Console.WriteLine("1 running");
int result1 = await Task.Run(() => Method2(0));
int result2 = await Task.Run(() => Method2(result1));
Thread.Sleep(1000);
Console.WriteLine("result " + result2 * 2);
}
what am i doing wrong here ?
When calling Method() you aren't waiting on it. It returns a task object that is not acted upon, and then Main() dutifully returns, which ends the program.
You can do this in Main():
public static void Main() {
Method1().GetAwaiter().GetResult();
}
Or use async Main() instead:
public static async Task Main() {
await Method1();
}
I wrote a command line program that lets two robots (Lifeguard and Superhero) wander randomly in a 22x22 matrix until they get to a square with the # symbol.
The direction choice of the robot Superhero is in contrast to the robot Lifeguard not equally distributed. Superhero chooses the direction north 66% of the time.
I can start both robots asynchronously via the menu. While the data for Lifeguard is available relatively fast, the program freezes because of Superhero. I assumed that it does not freeze because I am programming asynchronously. Where is the error?
using System.Diagnostics;
class Program {
public static async Task Main(string[] args) {
Map map = new Map();
Roboter l = new Roboter(map.defaultMap, "Lifesaver", 'L', 9);
Roboter s = new Roboter(map.defaultMap, "Superhero", 'S', 10);
map.spreadRoboters(l, s);
View view = new View(map.defaultMap);
Stopwatch watch = new Stopwatch();
Random rand = new Random();
string input = "start";
while (input != "exit") {
Console.WriteLine("choose an option:");
Console.WriteLine("1 start asynchronously");
Console.WriteLine("2 show Map");
Console.WriteLine("3 exit.");
input = Console.ReadLine();
switch (input) {
case "1":
await StartTaskAsync(l, s, rand, watch);
break;
case "2":
view.displayMap();
break;
case "exit":
input = "exit";
break;
default:
input = "exit";
break;
}
}
}
static async Task StartTaskAsync(Roboter l, Roboter s, Random r, Stopwatch watch) {
Task < string > lifesaverTask = StartLifesaverAsync(l, r, watch);
Task < string > superheroTask = StartSuperheroAsync(s, r, watch);
List < Task < string >> taskList = new List < Task < string >> {
lifesaverTask,
superheroTask
};
/* Task<string> completedTask = await Task.WhenAny(taskList);
string result = await completedTask;
Console.WriteLine(result);*/
while (taskList.Count > 0) {
Task < string > taskResult = await Task.WhenAny(taskList);
if (taskResult == lifesaverTask) {
Console.WriteLine(lifesaverTask.Result);
} else if (taskResult == superheroTask) {
Console.WriteLine(superheroTask.Result);
}
taskList.Remove(taskResult);
}
}
static async Task < string > StartLifesaverAsync(Roboter l, Random r, Stopwatch watch) {
return await Task.Run(() => {
int steps = 1;
string[] directions = new string[] {
"NORTH",
"SOUTH",
"WEST",
"EAST"
};
watch.Start();
while (l.state != true) {
int zufall = r.Next(0, 4);
string direction = directions[zufall];
l.move(direction, l.map);
steps++;
}
watch.Stop();
long time = watch.ElapsedMilliseconds;
l.reset(1, 1);
return "Lifesaver: steps: " + (steps).ToString() + ", time: " + time.ToString() + "ms";
});
}
static async Task < string > StartSuperheroAsync(Roboter s, Random r, Stopwatch watch) {
return await Task.Run(() => {
int steps = 1;
string[] directions = new string[] {
"NORTH",
"NORTH",
"NORTH",
"NORTH",
"NORTH",
"NORTH",
"SOUTH",
"WEST",
"EAST"
};
watch.Start();
while (s.state != true) {
int zufall = r.Next(0, 9);
string direction = directions[zufall];
s.move(direction, s.map);
steps++;
}
watch.Stop();
long time = watch.ElapsedMilliseconds;
s.reset(20, 20);
return "Superhero: steps: " + (steps).ToString() + ", time: " + time.ToString() + "ms";
});
}
}
I think there are at least two things a play here.
A. while(...)
while(something != true){ can be dangerous because they can run forever. You don't say how long "the program freezes" for so I'm not sure, but you may have a case where s.move(direction,s.map); never sets s.State to true.
You may want to protect yourself. Here's one option:
...
steps++;
if(steps > 1_000) throw ApplicationException("Something went wrong. Too many steps taken");
B. await Task.Run
await Task.Run(() => { will wait until the work is done.
If you want to start the task but not wait until it's finished don't await immediately. Here's a little example:
using System.Diagnostics;
var sw = Stopwatch.StartNew();
var t = Task.Run(() => { Console.WriteLine("Task 1 starting... Thread ID: {0}",Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);// Simulate a computationally heavy work
Console.WriteLine("Task 1 ending... thread ID: {0}",Thread.CurrentThread.ManagedThreadId);
});
var t2 = Task.Run(() => { Console.WriteLine("Task 2 starting... thread ID: {0}",Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);// Simulate a computationally heavy work
Console.WriteLine("Task 2 ending... thread ID: {0}",Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine("After starting both tasks. Task thread ID: {0}",Thread.CurrentThread.ManagedThreadId);
await Task.WhenAll(t, t2);
Console.WriteLine("Tasks finished. Task thread ID: {0}",Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(sw.Elapsed);
prints
After starting both tasks. Task thread ID: 1
Task 2 starting... thread ID: 5
Task 1 starting... Thread ID: 3
Task 1 ending... thread ID: 3
Task 2 ending... thread ID: 5
Tasks finished. Task thread ID: 5
00:00:02.0351754
I've just started learning C# and I'm trying to figure out threads.
So, I've made a two threads and I would like to stop one of them by pressing x.
So far when I press x it only shows on the console but it doesn't abort the thread.
I'm obviously doing something wronng so can someone please point out what I'm doing wrong? Thank you.
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
//Creating Threads
Thread t1 = new Thread(Method1)
{
Name = "Thread1"
};
Thread t4 = new Thread(Method4)
{
Name = "Thread4"
};
t1.Start();
t4.Start();
Console.WriteLine("Method4 has started. Press x to stop it. You have 5 SECONDS!!!");
var input = Console.ReadKey();
string input2 = input.Key.ToString();
Console.ReadKey();
if (input2 == "x")
{
t4.Abort();
Console.WriteLine("SUCCESS! You have stoped Thread4! Congrats.");
};
Console.Read();
}
static void Method1()
{
Console.WriteLine("Method1 Started using " + Thread.CurrentThread.Name);
for (int i = 1; i <= 5; i++)
{
Console.WriteLine("Method1: " + i);
System.Threading.Thread.Sleep(1000);
}
Console.WriteLine("Method1 Ended using " + Thread.CurrentThread.Name);
}
static void Method4()
{
Console.WriteLine("Method4 Started using " + Thread.CurrentThread.Name);
for (int i = 1; i <= 5; i++)
{
Console.WriteLine("Method4: " + i);
System.Threading.Thread.Sleep(1000);
}
Console.WriteLine("Method4 Ended using " + Thread.CurrentThread.Name);
}
It looks like you have a extra Console.ReadKey(); before if (input2 == "x"), that extra read causes the program to stop and wait before going inside your if statement waiting for a 2nd key to be pressed.
Also input.Key returns a enum, when you do the to string on it the enum will use a capital X because that is what it is set to. Either use input.KeyChar.ToString() to convert it to a string or use
var input = Console.ReadKey();
if (input.Key == ConsoleKey.X)
To compare against the enum instead of a string.
I also recommend you read the article "How to debug small programs", debugging is a skill you will need to learn to be able to write more complex programs. Stepping through the code with a debugger you would have seen input2 was equal to X so your if statement was
if ("X" == "x")
which is not true.
I am trying various options on working with threads. I wrote the code below, but it does not work as expected. How can I fix the code, so that the main function will correctly display the product?
using System;
using System.Threading;
namespace MultiThreads
{
class Program
{
static int prod;
public static void Main(string[] args)
{
Thread thread = new Thread(() => Multiply(2, 3));
thread.Start();
for(int i = 0; i < 10; i++) { // do some other work until thread completes
Console.Write(i + " ");
Thread.Sleep(100);
}
Console.WriteLine();
Console.WriteLine("Prod = " + prod); // I expect 6 and it shows 0
Console.ReadKey(true);
}
public static void Multiply(int a, int b)
{
Thread.Sleep(2000);
prod = a * b;
}
}
}
Ignoring the fact that you should be using non-blocking tasks, volatile properties and other coroutine principals, the immediate reason your program does not work as intended is because you didn't re-join the child thread back into the parent. See Join
Without the join, the Console.WriteLine("Prod = " + prod); occurs before the assignment prod = a * b;
static int prod;
static void Main(string[] args)
{
Thread thread = new Thread(() => Multiply(2, 3));
thread.Start();
for (int i = 0; i < 10; i++)
{ // do some other work until thread completes
Console.Write(i + " ");
Thread.Sleep(100);
}
thread.Join(); // Halt current thread until the other one finishes.
Console.WriteLine();
Console.WriteLine("Prod = " + prod); // I expect 6 and it shows 0
Console.ReadKey(true);
}
public static void Multiply(int a, int b)
{
Thread.Sleep(2000);
prod = a * b;
}
I wrote a small programm which prints "x", then "+", then again "x" and so on.
The idea was to make it run in two threads so that the first thread prints "x" and the second prints "+". The output looks like this:
"x" -> Thread number 1
"+" -> Thread number 2
"x" -> Thread number 1enter code here
"+" -> Thread number 2
and so on..
What I wrote seems to work fine but it seems to me it is written in
very old-fashioned way:
public class Example
{
private static int count = 10;
private static int i = 0;
private static bool isOneActive = false;
private static void Run1(object o)
{
string s = o as string;
while(true)
{
if (!isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = true;
if (i++ > count) break;
}
}
}
private static void Run2(object o)
{
string s = o as string;
while(true)
{
if (isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = false;
if (i++ > count) break;
}
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
I know that now .NET has a lot of instruments for thread synchronization as for example ManualResetEvent class and Task library. So how could we write the same programm using ManualResetEvent class? Is it possible at all?
Your code isn't only old fashioned, it is very inefficient. It spins for no reason doing nothing but waiting; this is called Busy wait should be avoided whenever possible.
Better approach is to use Waithandles as noted in comments.
A naive implementation with very little change in your code will look something like the following.
public class Example
{
private static int count = 10;
private static int i = 0;
private static AutoResetEvent firstEvent = new AutoResetEvent(true);
private static AutoResetEvent secondEvent = new AutoResetEvent(false);
private static void Run1(object o)
{
string s = o as string;
while (true)
{
firstEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
secondEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
private static void Run2(object o)
{
string s = o as string;
while (true)
{
secondEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
firstEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
}
Note that firstEvent is instantiated with the initialState flag set to true which means that first thread doesn't waits initially.
Consider this example (fiddle):
static void Main(string[] args)
{
var console = new object();
int i = 0;
Task.Run(() =>
{
lock (console)
while (i++ < 10)
{
Console.Write(i);
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Task.Run(() =>
{
lock (console)
while (i < 10)
{
Console.Write('+');
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Console.ReadLine(); // Task.WaitAll might be better, remove for fiddle
}