My problem is that the statusbar will get to 100% if the installation of DownloadInternetFile.exe will take to long time.
If i have a good connection it will work perfect, but if i have a bad connection i get a error saying the statusbar value can not be more than 100%.
if (Install_DownloadInternetFile == "Yes")
{
if (File.Exists("DownloadInternetFile.exe"))
{
var DownloadInternetFile = Process.Start("DownloadInternetFile.exe", "/q /norestart");
while (!DownloadInternetFile.HasExited)
{
this.LoadBar.Value += 1;
await Task.Delay(TimeSpan.FromSeconds(2));
}
DownloadInternetFile.WaitForExit();
}
else
{
TopMost = false;
MessageBox.Show("DownloadInternetFile.exe not found", "Error");
}
}
else
{
MessageBox.Show("Notselect");
}
LoadBar.Value = 8;
// start DownloadInternetFile2
if (Install_DownloadInternetFile2 == "Yes")
{
if (File.Exists("DownloadInternetFile2.exe"))
{
var Dotnet45 = Process.Start("DownloadInternetFile2.exe", "/q");
while (!DownloadInternetFile2.HasExited)
{
this.LoadBar.Value += 1;
await Task.Delay(TimeSpan.FromSeconds(2));
}
DownloadInternetFile2.WaitForExit();
}
else
{
TopMost = false;
MessageBox.Show("DownloadInternetFile2.exe not found", "Error");
}
}
else
{
MessageBox.Show("Notselect");
}
LoadBar.Value = 10;
the code gones on with 10 more exe files installing.
I think iam missing somthing in this part
this.LoadBar.Value += 1;
But can not figure it out
By default the "Value" property of the "ProgressBar" class can be in the range of 0 to 100. Your code does not intrinsically know how much of the work has been done unless you calculate it. However, in your loop you make no calculation as to how much work has been done, but instead adjust the value of the progress bar based on time. So if you know your task is going to take the same amount of time, no matter what the conditions, this is an acceptable calculation. However if the time your actions takes can vary you'll need to find some other way to calculate the value of the progress bar that reflects the true progress of the action. For example, if your action is a download then your bar should reflect the bytes downloaded divided by the total bytes of the download.
Related
Problem: I'm working on a calculator as my first MVVM application and have come across an interesting problem that I would like to understand better. My noob problem is that I'm trying to flash an error message for an invalid input--in this case I don't want the user to use the negate operator in an invalid location. In order to flash the message across the screen, I'm saving the display in another variable, setting the display to say "Invalid Operation", then I'd like to delay for half a second and reset the display to what it was before (from the temp variable). My problem is that the display variable gets set but the actual display doesn't update to show the error message, no matter how long the delay is.
I've tried both blocking (Thread.Sleep) and non-blocking delays (Task.Delay) within the function, writing separate functions to set and reset the display, and delaying within the Negate function instead, but none of these attempts allow the display to update. The display works as expected when adding and deleting characters in other parts of the code, so I don't think there's an issue with that.
Is this some sort of piping issue (the delay function actually starts before it can call the Display property) or something else entirely? I've checked other posts on here and those solutions don't seem to solve my issue. I'd love feedback on why this doesn't work as I'd expect it to as well as more efficient/effective ways to code this. Here are the relevant code blocks:
public void Negate()
{
if (Display.Length > 0)
{
if (Display[Display.Length - 1].Equals('-'))
{
Display = Display.Substring(0, Display.Length - 1);
}
else if (Display[Display.Length - 1].Equals(' ') || Display[Display.Length - 1].Equals('(') ||
Display[Display.Length - 1].Equals('E') || Display[Display.Length - 1].Equals('^'))
{
Display += '-';
}
else
{
InvalidOperation();
}
}
else
{
Display = "-";
}
}
public void InvalidOperation()
{
tempDisplay = Display;
Display = "Invalid Operation";
Thread.Sleep(500);
Display = tempDisplay;
}
public string Display
{
get
{
return _display;
}
set
{
_display = value;
OnPropertyChanged();
}
}
UI will be updated only after method InvalidOperation execution is complete, so because in last line of the method you set value back to original - there are no updates in UI.
Asynchronous approach should work, because await operator will "pause" InvalidOperation method and return execution to the message loop which will update UI controls.
public async Task InvalidOperation()
{
tempDisplay = Display;
Display = "Invalid Operation";
await Task.Delay(2000);
Display = tempDisplay;
}
I am working on a serial monitor project based on the arduino serial monitor, but with a lot of more functionalities. Serial monitor UI with messages every 2 seconds
There are 2 basic functions - reading serial data and visualising it to the richtextbox, writing serial data and also visualising it to the richtextbox. There is a problem when the communication is very intensive (arduino sends a line as fast as it can) and the user input cuts some of the recieved lines in halves. I made an algorythm to separate the input strings from the output strings in the richtextbox by setting sending/receiving flags. However this made the program act strange. Sometimes the command sent to the arduino just doesn't visualise in the richtextbox, but the data from the arduino is visualised just fine. I tried setting breakpoints on the user input visualising method and they were rarely activated. What is more I also set breakpoints on the visualisation of the read data method and they were also rarely activated. However the form was not lagging or freezing and the commands were flying in the richtextbox, contrary to the observed behaviour of the breakpoints. The printing algorythm is heavy, because I implemented multi-color printing.
What I tried:
-tried the blockingcollection approach. Just putting the printing actions in a queue and executing the actions one by one using 2 additional threads to the main one.(Task.Factory.StartNew). The problem was the queue was filled with over 3000 actions in the matter of a minute and the whole thing was lagging behind with like 15 seconds.
-i tried starting a new Task.Factory for every receive/send methods for every printing of a new command and locking the thread until the command is printed in the richtextbox. This is also too slow.
Finally I came up with the idea of just setting flags and allowing or not the print event. Using this approach the user input is almost never printed in the richtextbox. :(
Printing algorythm:
void printToConsole(string print, Color txtColor, string part, Color partColor, bool isMsg, bool endNL)
{
while (print.Contains('\r'))
print = print.Replace("\r", "");
for (int i = 0; i < print.Length; i++)
{
if (newString)
{
newString = false;
printTimeAndPart(part, partColor);
}
else if (i == 0 && !prevStrHadNL && isMsg != prevWasMsg)
{
printNLTimeAndPart(part, partColor);
}
else if (i == 0 && prevStrHadNL)
{
printNLTimeAndPart(part, partColor);
}
else if (i == print.Length - 1)
{
if (print[i] == '\n')
{
if (endNL && isMsg != prevWasMsg)
AppendText("\n");
prevStrHadNL = true;
break;
}
else
{
if (endNL)
AppendText("\n");
prevStrHadNL = false;
}
}
if (print[i] == '\n')
{
printNLTimeAndPart(part, partColor);
}
else
AppendText(print[i].ToString(), txtColor);
}
prevWasMsg = isMsg;
}
private void printNLTimeAndPart(string part, Color partColor)
{
AppendText("\n");
printTimeAndPart(part, partColor);
}
private void printTimeAndPart(string part, Color partColor)
{
if (timestamp == 1)
AppendText(DateTime.Now.ToString("HH:mm:ss.fff"), timeColor);
AppendText(part, partColor);
}
private void AppendText(string txt, Color clr)
{
if (serialControl.ReadAllowed)
{
if (rtArea.InvokeRequired)
{
MethodInvoker mi = delegate ()
{ rtArea.AppendText(txt, clr); };
Invoke(mi);
}
else
rtArea.AppendText(txt, clr);
}
}
private void AppendText(string txt)
{
if (serialControl.ReadAllowed)
{
if (rtArea.InvokeRequired)
{
MethodInvoker mi = delegate ()
{ rtArea.AppendText(txt); };
Invoke(mi);
}
else
rtArea.AppendText(txt);
}
}
Serial read data print:
wait1 and wait2 - flags. When wait1 is false there is no current user input message being printed.
When wait2 is false user input is free to print. If the access to a print operation was denied it is performed after the operation which blocked it. (At least that is the idea)
private void Port_dataRecieved(string a)
{
if (!consoleUsed)
{
newString = true;
consoleUsed = true;
}
inputVal = a;
if (!wait1)
{
inputAccDenied = false;
wait2 = true;
PrintInput(inputVal);
wait2 = false;
}
else
inputAccDenied = true;
if (msgAccDenied)
{
PrintMsg(msgVal);
msgAccDenied = false;
}
}
private void PrintInput(string input)
{
printToConsole(input, inTxtColor, inPrefix, inPrefColor, false, false);
}
This is the dataReceived method from my serial controller class:
I tried several ways to read serial data and the uncommented one is the most stable one I tried.
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
/* byte[] buffer = new byte[blockLimit];
Action kickoffRead = null;
kickoffRead = delegate
{
port.BaseStream.BeginRead(buffer, 0, buffer.Length, delegate (IAsyncResult ar)
{
try
{
int actualLength = port.BaseStream.EndRead(ar);
byte[] received = new byte[actualLength];
Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
string rcv = Encoding.Default.GetString(received);
dataRecieved(rcv);
}
catch (IOException exc)
{
//handleAppSerialError(exc);
}
kickoffRead();
}, null);
};
kickoffRead();
*/
if (ReadAllowed)
{
string a = port.ReadExisting();
//port.DiscardInBuffer();
dataRecieved(a); //Raise event and pass the string to Form1 serial_dataReceived
}
}
So, I need some advice on how exactly to print the multi-color messages without cutting into each other, printing every time, fast, with low cpu load (now it is like 35% on full load (arduino intensive transmittion) on i5-4310m). I would be glad if you could provide some examples, too.
I'm using an asynchronous method that sets a value. I want to see if the value remains the same within 10 seconds. If the value didn't change in this amount of time, it should enable a flag to do something else.
Is there a simple way to do it?
The timer should start when the value is changed and be checked (let's say maybe not every time which would be overkill but every 0.5 seconds) until the timer reached 10 seconds and then execute a method or change the value of a flag to false for example.
As I tried with another async method to be triggered when the value changed it didn't work. And it seemed to me to be very complicated to do.
/// <summary>
/// Asynchronously sends the commands to CWI
/// </summary>
private async void SendCommandToCWI(object sender, EventArgs e)
{
await Task.Delay(1);
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
//Here is some logic that will calculate many things to get the value of _axisX and _axisY.
//I deleted this part to show the code as it was unnecessary.
if (!(_axisX == 0 && _axisY == 0) && (PortVM != null) && PortVM.IsOpen)
{
CommandSender.AxisX(_axisX);
Thread.Sleep(50);
string indata = PortVM.ReadExisting();
//Debug.Print("Data Received:");
//Debug.Print(indata);
Console.WriteLine(_axisY);
Console.WriteLine(_axisX);
CommandSender.AxisY(_axisY);
}
else
{
PanelX = 0;
PanelY = 0;
_TimerInside.Stop();
_axisX = 0;
_axisY = 0;
CommandSender.AxisX(0);
CommandSender.AxisY(0);
CommandSender.AxisX(_axisX);
CommandSender.AxisY(_axisY);
}
});
}
So basically I want to see if every time I calculate _axisX and _axisY that after 10 seconds if the results remains the same it should whatever call a method or set a flag from true to false.
I have a class extracting strings from a large file (100,000) lines and wanted to give some progress feedback to the user. My problem is that the progress is not reported correctly.
I am using a custom class to send in the UserState property:
public enum UpdateType {FileCount, ProcessedFiles, LineCount, ProcessedLines, StepUpdate};
public class ProgressUpdate
{
public UpdateType UpdateType { get { } set { } }
public string Update { get { } set { } }
}
This is my method for handling the ReportProgress event:
public class BGWorkerBase : BackgroundWorker
{
public void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ProgressUpdate update;
update = (ProgressUpdate)e.UserState;
switch (update.UpdateType)
{
case UpdateType.FileCount:
MainWindow.FrmDisplayProgress.FileCount = update.Update;
break;
case UpdateType.ProcessedFiles:
MainWindow.FrmDisplayProgress.FileProgress = update.Update;
break;
case UpdateType.LineCount:
MainWindow.FrmDisplayProgress.LineCount = update.Update;
break;
case UpdateType.ProcessedLines:
MainWindow.FrmDisplayProgress.LineProgress = update.Update;
MainWindow.FrmDisplayProgress.PrecentProgress = e.ProgressPercentage;
break;
case UpdateType.StepUpdate:
MainWindow.FrmDisplayProgress.AddLine(update.Update);
break;
}
}
}
MainWindow.FrmDisplayProgress is a call to a form that displays progress.
And last, this is the worker class:
public class TraceFile
{
public HashSet<string> ExtractValues(HashSet<MyRegex> regexList, BackgroundWorker worker)
{
HashSet<string> results = new HashSet<string>();
int rowNumber = 1;
foreach (DataRow row in Lines.Rows)
{
int percentComplete = (int)(((float)rowNumber / (float)Lines.Rows.Count) * 100);
worker.ReportProgress(percentComplete, new ProgressUpdate(UpdateType.ProcessedLines, rowNumber++.ToString()));
// using multiple regex supports different formats for the same data type. For example - more then 1 account format
foreach (MyRegex regex in regexList)
{
MatchCollection matches = regex.Matches(row["Text"].ToString());
if (matches.Count > 0)
{
foreach (Match result in matches)
results.Add(result.ToString());
}
}
}
return results;
}
}
This is the case that catches these specific type of updates :
case UpdateType.ProcessedLines:
MainWindow.FrmDisplayProgress.LineProgress = update.Update;
MainWindow.FrmDisplayProgress.PrecentProgress = e.ProgressPercentage;
break;
'MainWindow.FrmDisplayProgress.PrecentProgress = e.ProgressPercentage;' is updating a progress bar. Instead of slowly moving from 0 to 100 once, the progress bar moves from 0 to 100 quickly several times.
'MainWindow.FrmDisplayProgress.LineProgress = update.Update' is updating a label with the line number but its not doing anything.
For some reason, while in debug mode I saw both updating correctly so I'm suspecting some threading issues.
I hope I managed to present all this in a clear manner.
Solution for the issue:
The progress bar running several times was a red herring and is not related to the issue. This happened becasue the method was entered several times.
The label not updating is due to too frequent calls (see the answer to this question below for more details). I changed the method to this:
public HashSet<string> ExtractValues(HashSet<MyRegex> regexList, BackgroundWorker worker)
{
HashSet<string> results = new HashSet<string>();
int rowNumber = 0;
DateTime startCount = DateTime.Now;
DateTime endCount = DateTime.Now;
foreach (DataRow row in Lines.Rows)
{
rowNumber++;
TimeSpan timeSpan = endCount.Subtract(startCount);
if ((timeSpan.Milliseconds > 50) | (rowNumber == Lines.Rows.Count))
{
int percentComplete = (int)(((float)rowNumber / (float)Lines.Rows.Count) * 100);
worker.ReportProgress(percentComplete, new ProgressUpdate(UpdateType.ProcessedLines, rowNumber.ToString()));
startCount = DateTime.Now;
}
// using multiple regex supports different formats for the same data type. For example - more then 1 account format
foreach (MyRegex regex in regexList)
{
MatchCollection matches = regex.Matches(row["Text"].ToString());
if (matches.Count > 0)
{
foreach (Match result in matches)
results.Add(result.ToString());
}
}
endCount = DateTime.Now;
}
return results;
}
You are calling ReportProgress too often. Call it more frequently than about a thousand times per second and the UI thread gets so swamped by the invoke requests that it doesn't get around to its regular duties anymore. It stops painting and paying attention to user input. The updates still happen, you just can't see them anymore.
This of course happens because you have ReportProgress inside the inner loop, calling it for each individual row in the dataset. It is wasted effort, the human eye cannot possibly keep up with that rate of updates, anything beyond 20 updates per second looks like a blur. A Q&D fix would be to call ReportProgress for every 100th row. Paying attention to elapsed time and count off 45 msec is the fix that works on any machine.
The problem with the progress bar sounds like a calculation problem, one that's not obvious from the snippet. The reason the progress bar works but not the text update is that PB was designed to avoid this painting problem, it forces a repaint when its Value property changes instead of waiting for Windows to deliver the Paint notification.
Instead of slowly moving from 0 to 100
once, the progress bar moves from 0 to
100 quickly several times.
Did you set the Minimum and Maximum of the progress bar to 0 and 100?
The defaults for a WPF ProgressBar is 0 and 1.
In case you are use a WinForms progress bar the default is 0 and 100, and that shouldn't be the problem.
I have recently implemented a scrolling text across an area of limited screen estate using a timers repeating every 100ms, and some simple string appending.
However, after this very implementation, I have come to realise that my GUI is getting randomly bugged/corrupted after a certain while. That is to say that some widgets/windows become completely white, and eventually the entire GUI turns white and unclickable.
What is weird is that there is no error debug output at all.
Having said that, I am using Mono with GTK-Sharp for the application. Does anyone have an idea or a possible clue how and why this is happening?
If not, how can I further debug this properly?
Thanks, really appreciate it.
PS: Sometimes, it takes up to 1.5 hours for the thing to start corrupting, it has random timeframes for it to start happening.
This is my the code implemented that caused this issue:
void ScrollSyncTo(object sender, System.Timers.ElapsedEventArgs e)
{
//initial check if it fits nicely alr
if (sync_to_full_txt.Length <= sync_to_max_char)
{
sync_to_timer.Stop();
return;
}
//check for pause
if (sync_to_pause >= 0)
{
sync_to_pause--;
return;
}
//check direction
int temp_psn;
string temp_str;
if (sync_to_direction)
{
temp_psn = sync_to_posn + 1;
if (sync_to_full_txt.Substring(temp_psn).Length < sync_to_max_char)
{
sync_to_pause = sync_to_break_steps;
sync_to_direction = false;
sync_to_posn = sync_to_full_txt.Length - 1;
System.GC.Collect();
return;
}
else
{
temp_str = sync_to_full_txt.Substring(temp_psn, sync_to_max_char);
}
}
else
{
temp_psn = sync_to_posn - 1;
if (temp_psn + 1 < sync_to_max_char)
{
sync_to_pause = sync_to_break_steps;
sync_to_direction = true;
sync_to_posn = 0;
System.GC.Collect();
return;
}
else
{
temp_str = sync_to_full_txt.Substring(temp_psn - sync_to_max_char + 1, sync_to_max_char);
}
}
//lets move it
sync_to.Text = temp_str;
sync_to_posn = temp_psn;
}
To program in GTK with multiple threads, you have to do a couple things to make your program thread-safe. Here is short explanation using C.
I'm more familiar with GTK in C, but I'm assuming it works the same in GTK#. So you have to call GLib.Thread.Init() and Gdk.Threads.Init() at the beginning of your program, bracket your call to Application.Run() with Gdk.Threads.Enter() and Gdk.Threads.Leave(), and also make sure any GTK and GDK calls in background threads (not GTK signal handlers) are between Gdk.Threads.Enter() and Gdk.Threads.Leave().
System.Timers.Timer callbacks come from a threadpool thread, but GTK objects can only safely be accessed from the GTK thread. I would suggest using GLib.Timeout, which runs on the GTK thread.