I have a application which programs firmware to a circuit board. In the application you can program a single board, or a tray. When programming a tray you can only load 14 at a time.
The user may want to program say 30 boards, so I want the program to program the 14 boards and then tell the user they need to reload a tray.
At the moment I only have one board to practice on, so I have just been reprogramming the same one pretending its a tray.
I have tried to resolve this using loops but when I press the start button it all freezes and stops responding.
The following is my code:
private void setFirmwareMultiple()
{
clearTicksandCrosses();
string firmwareLocation = Firmware(productComboBox.Text); //get the firmware location
string STPath = #"C:\Users\Falconex\Documents\FalconexTest\FalconexTest\ST-LINK Utility\ST-LINK_CLI.exe"; //file location
string result; //set string
string result2; //set string
int counter = 0;
int numberOfBoards = int.Parse(numberOfBoardsTextBox.Text);
while (numberOfBoards > counter) {
for (int i = 0; i > 14; i = i + 1) {
ProcessStartInfo start = new ProcessStartInfo(); //new process start info
start.FileName = STPath; //set file name
start.Arguments = "-C -ME -p " + firmwareLocation + " -v -Run"; //set arguments
start.UseShellExecute = false; //set shell execute (need this to redirect output)
start.RedirectStandardOutput = true; //redirect output
start.RedirectStandardInput = true; //redirect input
start.WindowStyle = ProcessWindowStyle.Hidden; //hide window
start.CreateNoWindow = true; //create no window
string picNumber = i.ToString();
using (Process process = Process.Start(start)) //create process
{
programmingTextBlock.Text = "Board Programming...";
System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Background,
new Action(delegate { }));
try
{
while (process.HasExited == false) //while open
{
process.StandardInput.WriteLine(); //send enter key
}
using (StreamReader reader = process.StandardOutput) //create stream reader
{
result = reader.ReadToEnd(); //read till end of process
File.WriteAllText("File.txt", result); //write to file
}
saveReport();
}
catch { } //so doesn't blow up
finally
{
int code = process.ExitCode; //get exit code
codee = code.ToString(); //set code to string
File.WriteAllText("Code.txt", codee); //save code
if (code == 0)
{
tick1.Visibility = Visibility.Visible;
counter = counter + 1;
}
else
{
cross1.Visibility = Visibility.Visible;
}
programmingTextBlock.Text = "";
}
}
System.Windows.MessageBox.Show("Load new boards");
}
}
}
I have put the total amount of boards the user wants in the for loop.
I think it maybe to do with the for loop. Because at first, in the for loop, I accidently put (i<14) and it caused it to run fine, however it then didn't stop.
Any help would be massively appreciated!
Thank you in advance,
Lucy
As the code stands now, your for loop's content never gets executed. The condition in the for loop is a continue condition. Since i is initialized with 0 the condition i > 14 is never met. So the result is an infinite outer while loop.
Your first "accident" with i < 14 was correct. But then the loop did not stop, because your inner while loop never finishes:
while (process.HasExited == false) //while open
{
process.StandardInput.WriteLine(); //send enter key
}
At first, please don't compare a bool to true or false. A simple while (!process.HasExited) is enough.
Secondly, you have to refresh your process instance to update the HasExited property correctly:
while (!process.HasExited) //while open
{
process.StandardInput.WriteLine(); //send enter key
process.Refresh(); // update the process's properties!
}
You may also consider to add a Thread.Sleep(...) in that loop.
The answer is simple:
while (numberOfBoards > counter) {
for (int i = 0; i > 14; i = i + 1) {
In the code above, the for loop will never be executed, because i will be always less than 14.
Because this, counter will never increment, and than, the while will never finish.
But besides this, your approach to the looping is wrong. The following example (fully test program) is something you should do instead:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int counter = 0;
int i = 0;
int numberOfBoards = 35;
for (; numberOfBoards > counter; i++, counter++)
{
Console.WriteLine("Counter {0}/i {1}", counter, i);
//call your thread here.
//make sure that he exists.
//use somekind of timeout to finish
//alert the user in case of failure but move to the next anyway to avoid an infinite looping.
if (i == 13) i = 0;
}
Console.WriteLine("Press any key");
Console.ReadKey();
}
}
}
Related
Newbie here! I've run into problems with some inconsistency when running the do while loop which surrounds the Try/Catch block.
Messing back and forth with different inputting makes the loop jump out despite its condition, which at multiple occasions should be true and run the block once again. Instead it ends up at "Number already exists" random number of times. It's obviously a hickup somewhere... Am I using it in the wrong way?
static void Main(string[] args)
{
int[] numbers = new int[10];
int input = 0;
int numRangeMin = 1;
int numRangeMax = 25;
bool duplicateNumber = false;
bool loop = true;
Console.WriteLine("\n Fill in a number:");
for (int i = 0; i < numbers.Length; i++)
{
do
{
do
{
try
{
Console.Write(" {0}: ", i + 1);
input = int.Parse(Console.ReadLine());
duplicateNumber = numbers.Contains(input); // Check if number already has been entered
loop = false;
}
catch (System.FormatException)
{ Console.WriteLine(" Only integers between {0}-{1} Try again!\n", numRangeMin, numRangeMax); }
catch (System.OverflowException)
{ Console.WriteLine(" Number is too big! Enter a number between {0}-{1}\n", numRangeMin, numRangeMax); }
} while (loop == true);
// Report if we attempt to insert a duplicate.
if (duplicateNumber)
{
Console.WriteLine("Number already exists");
}
else if (input > numRangeMax)
{
Console.WriteLine(" Too large:\n", numRangeMin, numRangeMax);
i--;
}
}
while (duplicateNumber == true); // Keep asking while we don't get a unique number.
numbers[i] = input; // Store the number
}
}
Your loop variable is defined outside the outer do loop, so it will retain it's value whenever you change it, that will lead to the inner loop not to be executed after the first time it has been set as false.
Define loop in side the outer loop or set it to true prior to the execution of the inner loop.
//...
do
{
loop = true;
do
{
try
{
//...
Also, the same will happen with the duplicateNumber variable because it's declared outside the for loop
This is a weird one, I have a Thread[] of worker threads which each process items in a ConcurrentQueue<string> until the queue is empty, at which point the rest of the program continues.
This works until about ~1500 items at which point all threads stay blocked in the WaitSleepJoin state and never process any of the items in the queue.
I've tried stepping through my code and it appears that the threads are still created, still started and are alive but get blocked immediately and never run their relevant function.
I'm completely flummoxed so any help would be appreciated!
The relevant sections of code are below:
Main Thread Segment:
ConcurrentQueue<string> convertionQueue = new ConcurrentQueue<string>();
List<Thread> converterThreads = new List<Thread>();
Directory.GetFiles(_folderOne, "*.fdf", SearchOption.AllDirectories).ToList().ForEach(file => convertionQueue.Enqueue(file));
Directory.GetFiles(_folderTwo, "*.fdf", SearchOption.AllDirectories).ToList().ForEach(file => convertionQueue.Enqueue(file));
int filesDone = 0;
int totalFiles = convertionQueue.Count;
progressBar.Maximum = totalFiles;
panel1.Visible = true;
for (int i = 0; i < Environment.ProcessorCount; i++)
{
converterThreads.Add(new Thread(() => ConvThreadWorker(convertionQueue, ref filesDone)));
}
converterThreads.ForEach(thread => thread.Start());
DateTime lastTick = DateTime.Now;
int lastFilesDone = 0;
int[] valuesSpeed = { 1, 1, 1, 1, 1 };
int[] valuesTime = { 1, 1, 1, 1, 1 };
int counter = 0;
while (converterThreads.Any(thread => thread.IsAlive))
{
TimeSpan t = DateTime.Now - lastTick;
int deltaFiles = filesDone - lastFilesDone;
double speed = (float)t.TotalMilliseconds <= 0.0 ? 0.0 : deltaFiles / (float)t.TotalMilliseconds;
double tMinus = speed <= 0 ? 0.0 : (totalFiles - filesDone) / speed;
int currentSpeed = (int)(speed * 1000);
int currentTime = (int)(tMinus / 1000);
valuesSpeed[counter] = currentSpeed;
valuesTime[counter] = currentTime;
lblFilesLeft.Text = string.Format("{0}/{1}", filesDone, totalFiles);
lblSpeed.Text = valuesSpeed.Sum() / 5 + " /s";
lblTime.Text = valuesTime.Sum() / 5 + " s";
lblFilesLeft.Update();
lblSpeed.Update();
lblTime.Update();
progressBar.Value = filesDone;
progressBar.Update();
lastTick = DateTime.Now;
lastFilesDone = filesDone;
counter = ++counter % 5;
Thread.Sleep(500);
}
Worker Function:
private void ConvThreadWorker(ConcurrentQueue<string> queue, ref int fileCounter)
{
while (!queue.IsEmpty)
{
string file;
if (queue.TryDequeue(out file))
{
ConvToG(file);
fileCounter++;
}
}
}
Convertion Function:
private void ConvToG(string file)
{
MessageBox.Show("Entering Convertion Function");
if (!_fileCreationDictionary.ContainsKey(file))
{
DateTime lastTimeModified = File.GetLastWriteTime(file);
_fileCreationDictionary.AddOrUpdate(file, lastTimeModified, (key,oldvalue)=>lastTimeModified);
}
ProcessStartInfo procStart = new ProcessStartInfo
{
Arguments = file,
UseShellExecute = true,
FileName = Fdfg,
WindowStyle = ProcessWindowStyle.Hidden
};
Process process = new Process {StartInfo = procStart};
MessageBox.Show("Starting convertion process");
process.Start();
process.WaitForExit();
MessageBox.Show("Finished");
}
The confusing part appears to be how this all revolves around the number of items in the queue, yet there appears to be no overflow.
UPDATE: Adding the mbox's shows that it freezes on the process.Start() section of code, with no errors and will not proceed past that point.
UPDATE 2: If UseShellExecute = false the code works. Which is very confusing to say the least.
I have done something similar with threads spawning processes to collate data. I had issues around the actual process starting and hanging. What I did to get my program working was something like this:
using (Process process = Process.Start(startInfo)) {
if(process.WaitForExit(timeOutMilliseconds)) {
MessageBox.Show("Process exited ok");
//...snip
} else {
MessageBox.Show("Process did not exit in time!");
//...snip
process.Kill();
}
}
There is a bit more going on in the background, regarding limiting the number of running process, etc, but I found that occasionally, for an unknown reason, that I would see several process in the task manager just hanging around forever.
Hope that helps?
I have a requirement for which I need my block of code to run infinitely (The exit is an interrupt based on button click).
In each iteration, I am creating a Process, starting it, manipulating the output and then disposing the Process.
void status()
{
do{
Process test1 = new Process();
test1.StartInfo.FileName = "doSomething"; // doSomething is executable
test1.StartInfo.UseShellExecute = false;
test1.StartInfo.CreateNoWindow = true;
test1.StartInfo.RedirectStandardOutput = true;
test1.StartInfo.RedirectStandardError = true;
test1.Start();
string output = test1.StandardOutput.ReadToEnd();
test1.WaitForExit();
if (Regex.IsMatch(output, "DEVICE_READY", RegexOptions.IgnoreCase))
{
pictureBox2.BackColor = Color.Green;
}
else
{
pictureBox2.BackColor = Color.Yellow;
}
test1.Dispose();
}while(true);
}
The problem is the application is crashing with this code. If I just remove the loop, it works fine.
I checked while debugging, memory usage of the application keeps on increasing with each iteration of the loop, making the application crash at one point.
What I understood is Dispose() will release all the resources... so memory should not increase with each iteration.
Could someone please help to understand what is causing the memory usage increase?
What I do when I have to deal with hungry processes (eg. pictures manipulation) is to call the garbage collector explicitly.
This is not the cleanest way (costs a lot), but reasonnably used, it does the trick.
void status()
{
// will be used to explicitly call the garbage collector
const int COLLECT_EVERY_X_ITERATION = 10;
// store the current loop number
int currentIterationCount = 0;
do
{
// increase current iteration count
currentIterationCount++;
using (Process test1 = new Process())
{
test1.StartInfo.FileName = "doSomething"; // doSomething is executable
test1.StartInfo.UseShellExecute = false;
test1.StartInfo.CreateNoWindow = true;
test1.StartInfo.RedirectStandardOutput = true;
test1.StartInfo.RedirectStandardError = true;
test1.Start();
string output = test1.StandardOutput.ReadToEnd();
test1.WaitForExit();
if (Regex.IsMatch(output, "DEVICE_READY", RegexOptions.IgnoreCase))
{
pictureBox2.BackColor = Color.Green;
}
else
{
pictureBox2.BackColor = Color.Yellow;
}
}
// Explicitly call garbage collection every 10 iterations
if (currentIterationCount % COLLECT_EVERY_X_ITERATION == 0)
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
} while (true);
}
I try to use Parallel.For to run process and get output parallelly.
Sample code like this:
internal class Program
{
private static void Main(string[] args)
{
var bag = new ConcurrentBag<string>();
Parallel.For(0, int.MaxValue, i =>
{
bag.Add(MyMethod());
});
}
public static string MyMethod()
{
using (var a = new Process())
{
a.StartInfo.FileName = "A.exe";
a.StartInfo.RedirectStandardError = true;
a.StartInfo.RedirectStandardInput = true;
a.StartInfo.RedirectStandardOutput = true;
a.StartInfo.CreateNoWindow = true;
a.StartInfo.UseShellExecute = false;
a.StartInfo.ErrorDialog = false;
a.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
a.Start();
string output = a.StandardOutput.ReadToEnd();
a.WaitForExit();
return output; // sometime output will be null
}
}
}
A.exe code
internal class Program
{
private static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 40; j++)
{
Console.Write("A");
}
Console.Write(Environment.NewLine);
}
}
}
Does anyone know why output will null and how could I avoid get null result?
I have tried to figure out why get null in stream.
If I add Thread.Sleep() before A.exe output, main process's ReadToEnd() will wait for A.exe output and get result.
Only one situation will cause null stream is the A.exe exit and no output.
This will let ReadToEnd() get null and Peek() didn't help because A.exe is exit and no longer output anymore.
I think my problem is my program is running at a heavy loading Windows Server 2003 R2 32bit, Process.Start() didn't get exception when the process can't start. It cause no output to stream, the process exit and stream close.
I'm a beginner in C#. I'm developing a console game and I have a problem with Thread in C#.
My game will display a top bar where count down timer runs. I try with a thread, I use Console.Clear() to clear old number then replace by new number on one line (59,58,57...). My game display a message to user input user's data on center screen or anywhere,...etc. But, when I start the thread countdown, it clear console screen, also, it clear message that user can input user's data. Can you help me and explain how to start 2 threads, do more various tasks?
using System; using System.Threading;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
Program m = new Program();
Thread pCountDown = new Thread(new ThreadStart(
m.DisplayCountDown
));
Thread pDisplayForm = new Thread(new ThreadStart(
m.DisplayForm
));
pCountDown.Start();
pDisplayForm.Start();
Console.ReadKey();
}
private void DisplayCountDown() {
for (int i = 60; i >= 0; --i) {
Console.Write("Time: {0}",i);
Thread.Sleep(1000);
Console.Clear();
}
}
private void DisplayForm() {
while (true) {
Console.Write("Enter your number: ");
int a = Int32.Parse(Console.ReadLine());
Console.WriteLine(a);
Console.ReadLine();
}
}
}
}
Error:
My error
I want like this:
Image (Sorry, i'm a new member): Like this
You don't need thread nor to clear the console. Simply use Console.SetCursorPosition() and Console.Write() as suggested here, so you can overwrite the number.
You do not need to clear the console. Console.Write() writes over the existing characters, so just change the cursor position with Console.SetCursorPosition(x,y);
For example:
string mystring = "put what you want to right here";
Console.SetCursorPosition(0,0); //the position starts at 0 just make a note of it
Conolse.Write(mystring);
//now when you are ready to clear the text and print something over it again
//just add this
//now first erase the previous text
for(int i = 0; i< mystring.Length; i++)
{
Console.SetCursorPosition(i,0);
Console.Write(' ');
}
//now write your new text
mystring = "something else";
Console.SetCursorPosition(0,0);
Console.Write("mystring");
Here's a sample DisplayCountDown which doesn't clear the whole screen every second:
private void DisplayCountDown()
{
for (int i = 20; i >= 0; --i)
{
int l = Console.CursorLeft;
int t = Console.CursorTop;
Console.CursorLeft = 0;
Console.CursorTop = 0;
Console.Write("Time: {0} ", i);
Console.CursorLeft = l;
Console.CursorTop = t;
Thread.Sleep(1000);
}
}
However, this still leaves some issues. In my case I saw "Enter your number" appearing on the top line and being overwritten, so had to add the line
if (Console.CursorTop == 0) Console.CursorTop = 1;
inside the while loop. Also, if the user enters enough numbers, the countdown scrolls out of view, and if you try to scroll up to look at it, setting the cursor position automatically scrolls back.
I also had intermittent issues with int.Parse throwing an exception, presumably caused by the countdown changing at some critical point of the user's input.