Starting up several programs at once - c#

I have written a small program (ProcessSample) to launch another programs that are defined in the .txt file (separated by new line).
The code is mostly taken from MSDN. I am just starting my programming adventure but I want to write something useful.
I don't know the smart way to run for example two programs simultaneously from my ProcessSample program.
In my .txt file I have just paths to programs with .exe. It's all working fine but my program is only running one program at the time. I thought I would run foreach but of course it won't work here as it just runs the first program and it waits till I exit it, then it will run the next one.
So I know the reason why is it not working. I just want to know how could I make it work the way I would like.
My C# code:
using System;
using System.Diagnostics;
using System.Threading;
namespace ProcessSample
{
class ProcessMonitorSample
{
public static void Main()
{
Console.BufferHeight = 25;
// Define variables to track the peak memory usage of the process.
long peakWorkingSet = 0;
string[] Programs = System.IO.File.ReadAllLines(#"C:\Programs\list.txt");
foreach (string Program in Programs)
{
Process myProcess = null;
// Start the process.
myProcess = Process.Start(#Program);
// Display the process statistics until
// the user closes the program.
do
{
if (!myProcess.HasExited)
{
// Refresh the current process property values.
myProcess.Refresh();
// Display current process statistics.
Console.WriteLine();
Console.WriteLine("Path: {0}, RAM: {1}", Program, (myProcess.WorkingSet64 / 1024 / 1024));
// Update the values for the overall peak memory statistics.
peakWorkingSet = myProcess.PeakWorkingSet64;
if (myProcess.Responding)
{
Console.WriteLine("Status: Running");
}
else
{
Console.WriteLine("Status: Not Responding!");
}
// Wait 2 seconds
Thread.Sleep(2000);
} // if
} // do
while (!myProcess.WaitForExit(1000));
Console.WriteLine();
Console.WriteLine("Process exit code: {0}", myProcess.ExitCode);
Console.WriteLine("Peak physical memory usage of the process: {0}", (peakWorkingSet / 1024 / 1024));
Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
} // foreach
} // public
} //class
} // namespace

The problem is in the inner while loop. There you are getting statistics from the running process and displaying them in the console. As far as I understand from your post, you don't need this feature so you can remove it and you would get:
using System;
using System.Diagnostics;
using System.Threading;
namespace ProcessSample
{
class ProcessMonitorSample
{
public static void Main()
{
Console.BufferHeight = 25;
// Define variables to track the peak memory usage of the process.
long peakWorkingSet = 0;
string[] Programs = System.IO.File.ReadAllLines(#"C:\Programs\list.txt");
foreach (string Program in Programs)
{
Process myProcess = null;
// Start the process.
myProcess = Process.Start(#Program);
Console.WriteLine("Program started: {0}", Program);
}
}
}
}

Actually I have learned about Threads and I have used them for my program like this:
class Program
{
static void Main(string[] args)
{
string[] myApps = { "notepad.exe", "calc.exe", "explorer.exe" };
Thread w;
ParameterizedThreadStart ts = new ParameterizedThreadStart(StartMyApp);
foreach (var myApp in myApps)
{
w = new Thread(ts);
w.Start(myApp);
Thread.Sleep(1000);
}
}
private static void StartMyApp(object myAppPath)
{
ProcessStartInfo myInfoProcess = new ProcessStartInfo();
myInfoProcess.FileName = myAppPath.ToString();
myInfoProcess.WindowStyle = ProcessWindowStyle.Minimized;
Process myProcess = Process.Start(myInfoProcess);
do
{
if (!myProcess.HasExited)
{
myProcess.Refresh(); // Refresh the current process property values.
Console.WriteLine(myProcess.ProcessName+" RAM: "+(myProcess.WorkingSet64 / 1024 / 1024).ToString()+"\n");
Thread.Sleep(1000);
}
}
while (!myProcess.WaitForExit(1000));
}
}

You can replace your foreach with Parallel.ForEach to achieve what you want.
Parallel.ForEach<String>(Programs, Program =>
{
Process myProcess = null;
// Start the process.
myProcess = Process.Start(#Program);
// Display the process statistics until
// the user closes the program.
do
{
if (!myProcess.HasExited)
{
// Refresh the current process property values.
myProcess.Refresh();
// Display current process statistics.
Console.WriteLine();
Console.WriteLine("Path: {0}, RAM: {1}", Program, (myProcess.WorkingSet64 / 1024 / 1024));
// Update the values for the overall peak memory statistics.
peakWorkingSet = myProcess.PeakWorkingSet64;
if (myProcess.Responding)
{
Console.WriteLine("Status: Running");
}
else
{
Console.WriteLine("Status: Not Responding!");
}
// Wait 2 seconds
Thread.Sleep(2000);
}
}
while (!myProcess.WaitForExit(1000));
Console.WriteLine();
Console.WriteLine("Process exit code: {0}", myProcess.ExitCode);
Console.WriteLine("Peak physical memory usage of the process: {0}", (peakWorkingSet / 1024 / 1024));
Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
});

Related

How to ask user same question in c# console app until time countdown expires?

Hi I am trying to make a console app that ask the user repeatedly to input a word until the time expires.
I have manage to use this for display the counter
`
for (int a = 20; a >= 0; a--)
{
Console.Write("\rTIME COUNTDOWN {0:00}", a);
System.Threading.Thread.Sleep(1000);
}`
The console will ask the user to input a word, I want to read the input and then repeat the question and read again input until the time expires.
Console.WriteLine($"insert word");
var input = Console.ReadLine();
How can I achieve this? Any help?
you can use WaitHandle.WaitOne method
the countdown loop will run and the user will enter an input and when the countdown is finished, the score will be printed and the thread will be finished and there will be a signal to print the user score.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static AutoResetEvent autoEvent = new AutoResetEvent(false);
static bool flg = true;
static int count = 20;
static void Main()
{
Console.WriteLine($"insert word");
for (int a = 20; a >= 0; a--)
{
//Console.WriteLine("\rTIME COUNTDOWN {0:00}", a);
System.Threading.Thread.Sleep(1000);
count = a;
ThreadPool.QueueUserWorkItem(
new WaitCallback(GetInputFromUser), autoEvent);
}
// Wait for GetInputFromUser method to signal.
autoEvent.WaitOne();
Console.WriteLine("you scored x points");
}
static void GetInputFromUser(object stateInfo)
{
if (Console.KeyAvailable || flg)
{
flg = false;
var input = Console.ReadLine();
Console.WriteLine($"insert word");
}
((AutoResetEvent)stateInfo).Set();
}
}
}

C# Why is Serial.WriteLine() so slow?

When I want to program a Teensy 3.5 micro-controller, I send it a .HEX file via a hardware serial port. I have two ways of doing this; one way is to use a serial comms app like Tera Term to send the file, and another way is via a small C# command-line app I wrote to do the same thing.
When I send a 3000+ line Hex file to the micro-controller, it takes approximately 14 seconds. When I do the same thing with my C# program, it takes twice as long (or longer!). The baud rate for both Tera Term and my C# program are the same, and of course the Teensy setup is common to both.
When I looked as the serial transfer using a digital scope, I see the following (same time scale in both photos):
The first photo shows the transfer when using Tera Term, and the second one shows the transfer when using my C# program using Serial.WriteLine() to transfer file contents line-by-line, as shown below:
using System;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Timers;
using System.Diagnostics;
/*
Small console app to facilitate over-the-air (OTA) updates to a Teensy 3.x/4.x controller,
using VS2019 with the Visual Micro extension as the Arduino IDE. It is called by a post-build
'hook' statement in a file called 'board.txt' located in whatever Teensy program is
being updated. This app does the following:
- Extract the project path and selected COMPORT number from the arguments to the call to Main()
- Opens a UART serial port connection to the Teensy, typically one provided by a BT adaptor
operating in 'pass-through' mode. The serial port COMPORT number is passed into this app
as an argument.
- Sends whatever command is required to put the existing Teensy firmware into 'update' mode
- Using the path of the updating program (passed in as an argument), locates the .HEX file
associated with the project, and sends it's contents to the Teensy, one line at a time, counting
lines and confirming checksums line-by-line
- Compares the number of lines sent to the Teensy with the number of lines received by the Teensy,
and if there is a match, allows the Teensy update process to complete; otherwise aborts
*/
namespace TeensyFlash
{
class Program
{
const string startCmdStr = "U"; //used in sketch's 'GetUserInput()' to start upload sequence
static string rcvStr = string.Empty;
private static System.Timers.Timer aTimer;
private static bool bTimedOut;
static void Main(string[] args)
{
//Extract the build path and selected COMPORT number from the arguments to the call to Main()
Console.WriteLine("Teensy Flash Console");
Console.WriteLine("Number of arguments in args = {0}\n", args.Length);
int argindex = 0;
string comPortStr = string.Empty;
foreach (var item in args)
{
Console.WriteLine(item);
if (item.Contains("COM"))
{
comPortStr = args[argindex];
}
argindex++;
}
string build_path = args[0];
string projectName = args[args.Length - 1];
projectName = projectName.Substring(0, projectName.Length - 4); //remove extension
build_path = build_path.Replace("\"", string.Empty).Trim();
string hexfilename = build_path + "\\" + projectName + ".hex";
Console.WriteLine("path = {0}", build_path);
Console.WriteLine("comport = {0}", comPortStr);
Console.WriteLine("build name = {0}", projectName);
Console.WriteLine("path to HEX file = {0}", hexfilename);
try
{
Stopwatch stopwatch = Stopwatch.StartNew();
string[] lines = System.IO.File.ReadAllLines(hexfilename);
foreach (string item in lines)
{
Console.WriteLine(item);
}
Console.WriteLine("this took " + stopwatch.ElapsedMilliseconds + " Msec");
}
catch (Exception)
{
throw;
}
Console.WriteLine("Opening Serial Port...");
try
{
SerialPort _serport = new SerialPort(comPortStr, 115200);
_serport.WriteTimeout = 1000;
_serport.WriteBufferSize = 20480;
_serport.Open();
_serport.DiscardOutBuffer();
_serport.DiscardInBuffer();
Thread.Sleep(100);
Console.WriteLine("Sending Trigger Character " + startCmdStr);
Console.WriteLine(startCmdStr);
_serport.Write(startCmdStr);
Console.WriteLine("Waiting for 'waiting' from Teensy...");
rcvStr = string.Empty;
aTimer = new System.Timers.Timer();
//aTimer.Interval = 5000;
aTimer.Interval = 25000;
aTimer.Elapsed += OnTimedEvent;
aTimer.Start();
while (!rcvStr.Contains("waiting") && !bTimedOut)
{
if (_serport.BytesToRead > 0)
{
rcvStr = _serport.ReadLine();
}
}
aTimer.Stop();
if (bTimedOut)
{
Console.WriteLine("Timed out waiting for 'waiting' response from Teensy");
}
else
{
//if we get to here, the Teensy is ready to receive HEX file contents
Console.WriteLine("Received " + rcvStr + " from Teensy");
Stopwatch stopwatch2 = Stopwatch.StartNew();
int numlines = 0;
string[] lines = System.IO.File.ReadAllLines(hexfilename);
foreach (string item in lines)
{
numlines++;
_serport.WriteLine(item);
}
Console.WriteLine("total lines = {0}, time = {1} mSec", numlines, stopwatch2.ElapsedMilliseconds);
//now we wait for Teensy to emit "hex file: xx lines xx bytes..." and then "enter xx to flash..."
aTimer.Start();
while (!rcvStr.Contains("hex file:") && !bTimedOut)
{
if (_serport.BytesToRead > 0)
{
rcvStr = _serport.ReadLine();
}
}
aTimer.Stop();
aTimer.Dispose();
if (bTimedOut)
{
Console.WriteLine("Timed out waiting for 'hex file' response from Teensy");
}
else
{
//extract number of lines from Teensy string, and compare with numlines.
//If they match, then send the number back to Teensy to complete the update.
//Otherwise, send '0' to abort
int colonIdx = rcvStr.IndexOf(':');
int lineIdx = rcvStr.IndexOf("lines");
string compareStr = rcvStr.Substring(colonIdx + 1, lineIdx - colonIdx - 1);
compareStr = compareStr.Trim();
int numTeensyLines = Convert.ToInt16(compareStr);
Console.WriteLine("sent {0} teensy replied {1}", numlines, numTeensyLines);
if (numTeensyLines == numlines)
{
Console.WriteLine("numlines {0} matches numTeensyLines {1} - send confirmation",
numlines, numTeensyLines);
_serport.WriteLine(compareStr);
}
}
}
}
catch (Exception)
{
throw;
}
try
{
}
catch (Exception)
{
throw;
}
}
static string chksum(string input)
{
int TwosComplement(string s)
{
if (s.Length % 2 != 0)
throw new FormatException(nameof(input));
var checksum = 0;
for (var i = 0; i < s.Length; i += 2)
{
var value = int.Parse(s.Substring(i, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
checksum = (checksum + value) & 0xFF;
}
return 256 - checksum & 0xFF;
}
//return string.Concat(":", input, " ", TwosComplement(input).ToString("X2"));
return TwosComplement(input).ToString("X2");
}
private static void SetTimer()
{
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
//aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
e.SignalTime);
bTimedOut = true;
}
}
}
The code that actually does the file transfer is:
Stopwatch stopwatch2 = Stopwatch.StartNew();
int numlines = 0;
string[] lines = System.IO.File.ReadAllLines(hexfilename);
foreach (string item in lines)
{
numlines++;
_serport.WriteLine(item);
}
Console.WriteLine("total lines = {0}, time = {1} mSec", numlines, stopwatch2.ElapsedMilliseconds);
When the '_serport.WriteLine(item);' line is commented out, the reported elapsed time is 0 mSec, as expected - so the 'ReadAllLines()' step isn't the problem.
Anyone have an idea why the 'WriteLine(item)' processing is so slow?
It depends on the structure of the method itself with the device, but I found on the same site an inquiry and means for it that help you
stackoverflow: console writeline slow

Why don't the "sync blocks" reduce automatically?

The example code below allocates a large number of sync blocks. This is displayed in Performance Monitor as "# of sink blocks in use". However after releasing the locks, the counter will not decrease until I manually call GC.Collect(). Why doesn't this happen automatic or isn't this a problem?
using System;
using System.Collections.Generic;
using System.Threading;
namespace locktest
{
public class Program
{
static void Main(string[] args)
{
var list1 = new List<Object>();
int threadcount = 0;
const int maxthreads = 9000;
for (int i = 0; i < maxthreads; i++)
{
var obj = new Object();
list1.Add(obj);
Monitor.Enter(obj); // this will initially use just a thin lock
// lock from a different thread to move to the sync blocks table
ThreadPool.QueueUserWorkItem(o =>
{
Monitor.TryEnter(o, 1);
Interlocked.Increment(ref threadcount);
}, obj);
}
while (threadcount < maxthreads)
Thread.Sleep(100); // wait until all threads have been finished
foreach (var obj in list1)
Monitor.Exit(obj); // release the locks
list1.Clear();
Console.WriteLine("Press enter to force GC.");
Console.ReadKey();
GC.Collect(); // this will reduce the number of sync blocks to almost 0
Console.WriteLine("Press enter to quit.");
Console.ReadKey();
}
}
}
related: What is a “Sync Block” and tips for reducing the count

More efficient way to calculate CPU Usage

So I'm writing a task manager clone, and right now I'm using this to calculate the CPU usage %s of each process. The problem is this is very slow; I was just wondering if there is a way to speed this up.
Also, I'm not allowed to use PerformanceCounter's methods and/or WMI.
//Omitted:
// - Process[] processes just holds the currently running processes
// - rows[] is a list of the rows I have in a table which shows the tables data
// - rows[2] is the column for CPU usage
// - rows[0] is the column for PID
//========
//Do CPU usages
double totalCPUTime = 0;
foreach (Process p in processes)
{
try
{
totalCPUTime += p.TotalProcessorTime.TotalMilliseconds;
}
catch (System.ComponentModel.Win32Exception e)
{
//Some processes do not give access rights to view their time.
}
}
foreach (Process p in processes)
{
double millis = 0;
try
{
millis = p.TotalProcessorTime.TotalMilliseconds;
}
catch (System.ComponentModel.Win32Exception e)
{
//Some processes do not give access rights to view their time.
}
double pct = 100 * millis / totalCPUTime;
for (int i = 0; i < rows.Count; i++)
{
if(rows[i].Cells[0].Value.Equals(p.Id))
{
rows[i].Cells[2].Value = pct;
break;
}
}
}
Use PerformanceCounter components to get different performance statistics:
var cpuCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
double value = cpuCounter.NextValue();
And here is sample of creating something like task manager.
Also consider using Win API function GetProcessTimes.

How to loop a Console App

i just need to be able to loop a console app. what i mean by that is:
program start:
display text
get input
do calculation
display result
display text
get input.
REPEAT PROCESS INFINATE NUMBER OF TIMES UNTIL THE USER EXITS THE APPLICATION.
program end.
i hope that made sense. can anyone please explain how i would go about doing this? thank you :)
Console.WriteLine("bla bla - enter xx to exit");
string line;
while((line = Console.ReadLine()) != "xx")
{
string result = DoSomethingWithThis(line);
Console.WriteLine(result);
}
while(true) {
DisplayText();
GetInput();
DoCalculation();
DisplayResult();
DisplayText();
GetInput();
}
The user can stop the program at any point with CTRL-C.
Is this what you meant?
You could wrap the whole body of your Main method in program.cs in a while loop with a condition that will always be satisfied.
E.g (in pseudo-code)
While (true)
{
Body
}
Kindness,
Dan
Use a While loop
bool userWantsToExit = false;
get input
while(!userWantsToExit)
{
do calc;
display results;
display text;
get input;
if (input == "exit")
userWantsToExit = true;
}
program end;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace InputLoop
{
class Program
{
static long PrintFPSEveryXMilliseconds = 5000;
static double LimitFPSTo = 10.0;
static void Main(string[] args)
{
ConsoleKeyInfo Key = new ConsoleKeyInfo(' ', ConsoleKey.Spacebar, false, false, false);
long TotalFrameCount = 0;
long FrameCount = 0;
double LimitFrameTime = 1000.0 / LimitFPSTo;
do
{
Stopwatch FPSTimer = Stopwatch.StartNew();
while (!Console.KeyAvailable)
{
//Start of Tick
Stopwatch SW = Stopwatch.StartNew();
//The Actual Tick
Tick();
//End of Tick
SW.Stop();
++TotalFrameCount;
++FrameCount;
if (FPSTimer.ElapsedMilliseconds > PrintFPSEveryXMilliseconds)
{
FrameCount = PrintFPS(FrameCount, FPSTimer);
}
if (SW.Elapsed.TotalMilliseconds < LimitFrameTime)
{
Thread.Sleep(Convert.ToInt32(LimitFrameTime - SW.Elapsed.TotalMilliseconds));
}
else
{
Thread.Yield();
}
}
//Print out and reset current FPS
FrameCount = PrintFPS(FrameCount, FPSTimer);
//Read input
Key = Console.ReadKey();
//Process input
ProcessInput(Key);
} while (Key.Key != ConsoleKey.Escape);
}
private static long PrintFPS(long FrameCount, Stopwatch FPSTimer)
{
FPSTimer.Stop();
Console.WriteLine("FPS: {0}", FrameCount / FPSTimer.Elapsed.TotalSeconds);
//Reset frame count and timer
FrameCount = 0;
FPSTimer.Reset();
FPSTimer.Start();
return FrameCount;
}
public static void Tick()
{
Console.Write(".");
}
public static void ProcessInput(ConsoleKeyInfo Key)
{
Console.WriteLine("Pressed {0} Key", Key.KeyChar.ToString());
}
}
}
You can just put a loop around whatever you're doing in your program.

Categories