When I run my code, the line:
WriteLine("Saved Files " + saveFiles + "\n");
comes out before the other output lines preceding it. How can I fix this? Code is below.
Here is also a short video of me demonstrating what I mean too but the code is below. Full code here. Thanks so much.
using DemoMemento;
using System.Windows;
using static System.Diagnostics.Debug;
// This Memento patter will create a caretaker that contains the collection
// with all the Statements in it. It can add and
// retrieve Statements from the collection
namespace Memento
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Caretaker caretaker = new Caretaker();
// The originator sets the value for the statement,
// creates a new memento with a new statement, and
// gets the statement stored in the current memento
Originator originator = new Originator();
int saveFiles = 0, currentStatement = -1;
// ---------------------------------------------
public MainWindow()
{
InitializeComponent();
}
private void btnSave_Click(object sender, RoutedEventArgs e)
{
// Get text in TextBox
string text = theStatement.Text;
// Set the value for the current memento
originator.set(text);
// Add new statement to the collection
caretaker.addMemento(originator.storeInMemento());
// saveFiles monitors how many statements are saved
// Number of mementos I have
saveFiles++;
currentStatement++;
WriteLine("Saved Files " + saveFiles + "\n");
btnUndo.IsEnabled = true;
}
private void btnUndo_Click(object sender, RoutedEventArgs e)
{
if (currentStatement >= 1)
{
currentStatement--;
string textBoxString = originator.restoreFromMemento(caretaker.getMemento(currentStatement));
theStatement.Text = textBoxString;
btnRedo.IsEnabled = true;
}
else {
btnUndo.IsEnabled = false;
}
}
private void btnRedo_Click(object sender, RoutedEventArgs e)
{
if ((saveFiles - 1)> currentStatement)
{
currentStatement++;
string textBoxString = originator.restoreFromMemento(caretaker.getMemento(currentStatement));
theStatement.Text = textBoxString;
btnUndo.IsEnabled = false;
}
else
{
btnRedo.IsEnabled = false;
}
btnUndo.IsEnabled = true;
}
}
}
The one output code uses Debug.WriteLine(), the others use Console.WriteLine(). These are two different ways of sending text to the output console which operate in parallel, asynchronously and independent of each other. Using Debug.WriteLine is usually faster than Console.WriteLine and wins the race unless you delay it by halting at a breakpoint before it is executed.
Debug.WriteLine is faster because it directly communicates with the Debugger, while Console.WriteLine takes a detour by writing into a pipe that the Debugger has to read from.
Imagine the difference between sending a letter and sending an email. The email arrives earlier than the letter even when it was sent some time after sending the letter.
Solution: Consistently only use Debug.WriteLine or only Console.WriteLine. Don't mix the two.
Related
I'm writing a FlashCard app in Windows Form.
Right now I'm trying to do is read word from string array and pass it to label. Then asking user to write the translation of this word. And finally pass the result to label box.
Here is my code:
public partial class EnglishPolishScreen : Form
{
//English words array
string[] words = new string[] { "word1", "word2", "word3", "word4" };
// meanings words array
string[] wordB = new string[] { "slowo1", "slowo2", "slowo3", "slowo4" };
int element = 0;
Thread thread;
public EnglishPolishScreen()
{
InitializeComponent();
}
private void CloseAppEvent(object sender, FormClosingEventArgs e)
{
Application.Exit();
}
private void button1_Click(object sender, EventArgs e)
{
thread = new Thread(Threadd);
thread.Start();
}
private void Threadd()
{
englishWord.Text = words[element];
counterLabel.Text = element + 1 + " of " + words.Length;
if (answerBox.Text.Equals(wordB[element]))
{
resultLabel.Text = "Good";
element++;
}
else
resultLabel.Text = "Bad";
if (element == words.Length)
{
element = 0;
}
}
private void EnglishPolishScreen_Load(object sender, EventArgs e)
{
englishWord.Text = words[element];
}
Edited
Guys, Why I have to click two times in button to see next item from array? And why I can see "bad" answer straight after I click button? The "Good" answer shows up after second click.
Edited v2.xD
Sorted. Anyway is it good way to write code like this? If not how It could look better? Thanks
Regards
On button click, it is going through the whole for loop, i.e. the entire list of meanings, you would have to break the for loop as soon as a right match is found. So just use break; after resoultLabel.Text = "Good answer!";. Also as pointed out by #Neil, it is not good to use UI in a separate background thread.
By the way, I am not able to wrap my head around the logic of chances. For giving chances you would have to declare a global variable which would get added/subtracted when the a bad answer is found after Iterating through whole for loop, disallowing any further trial for the word.
I have some code that I found here. It traps the output from cmd.exe and also sends input to it. I am using it (heavily modified) on a form in our application. It works well so we can hide cmd.exe from the users but allow this form to administrators. Other benefits include a favorites list, ect.
Here is some code. Note: I deleted 70% of the code to simplify it so there may be issues. If anyone wishes to run this code and they are having problems let me know and I will edit it and make sure it works. All it needs is a form with two textboxes, txtConsoleIn and txtConsoleOut plus a timer; tmrSelectedCommand.
public partial class frmCommandPrompt : Form
{
private bool CancelOutput;
private bool FirstTime = true;
private bool InternalCommand;
private string InternalCommandResponse;
private ProcessStartInfo psi;
private Process p;
private string SelectedCommand;
private bool SelectedCommandExecuteNow;
private delegate void InvokeWithString(string text);
public frmCommandPrompt()
{
InitializeComponent();
}
private void frmCommandPrompt_Shown(object sender, EventArgs e)
{
this.txtConsoleIn.Select();
}
private void tmrSelectedCommand_Tick(object sender, EventArgs e)
{
tmrSelectedCommand.Enabled = false;
if (SelectedCommand != string.Empty)
{
if (SelectedCommandExecuteNow)
{
ExecuteCommand(SelectedCommand);
}
else
{
txtConsoleIn.Text = SelectedCommand;
txtConsoleIn.SelectionStart = txtConsoleIn.Text.Length;
txtConsoleIn.Select();
}
SelectedCommand = string.Empty;
SelectedCommandExecuteNow = false;
}
}
// Sending console commands
private void txtConsoleIn_KeyUp(object sender, KeyEventArgs e)
{
string Command;
if ((int)e.KeyCode == (int)Keys.Return)
{
InternalCommand = false;
Command = txtConsoleIn.Text;
ExecuteCommand(Command);
txtConsoleIn.Clear();
}
}
private void Async_Data_Received(Object sender, DataReceivedEventArgs e)
{
if (this.IsHandleCreated)
{
this.Invoke(new InvokeWithString(Sync_Output), e.Data);
}
}
private void Sync_Output(string text)
{
if (!InternalCommand)
{
if (!CancelOutput)
{
OutputText(text);
}
}
else
{
if (text != String.Empty)
{
InternalCommandResponse = text;
InternalCommand = false;
}
}
}
private void ExecuteRecentCommand(string Command, bool ExecuteNow)
{
SelectedCommand = Command;
SelectedCommandExecuteNow = ExecuteNow;
tmrSelectedCommand.Enabled = true;
}
private void ExecuteCommand(string Command)
{
CancelOutput = false;
p.StandardInput.WriteLine(Command);
}
private void OutputText(string text)
{
txtConsoleOut.AppendText(text + Environment.NewLine);
txtConsoleOut.ScrollToCaret();
}
}
I would like to display the path, like prompt=$P$G. I can issue the command echo %cd% and trap the output while suppressing both that command and output. I
can then output this and add a ">." So far so good. Now the problem.
Sometimes commands can change the path. So I need to check the path again, but when? What if someone enters a long running command? How do I know when it is done? I would prefer to make this work as closely to the original cmd.exe as possible for ease of use.
is cd the only command that changes the path (besides a poorly written batch file)? If so I can check the path after that command. But I will have to use a label since a command like dir *.txt /s issued from the root can take some time and it will not only look stupid to throw the path in the middle of that output but will make the form less useable than not even displaying the path at all.
Or maybe have a timer starting another instance of cmd.exe running every 20 seconds or so just to get the path and display it in a label. Sounds like a lot of wasted cycles for little gain.
At this point the best bet seems to force the users to check the path themselves. I can add a button to get the path to make it easier but I would prefer a nicer solution.
I am building a program in C# to be used in one of my course at a college to demonstrate how Asynchronous connections work using RS-232 and two computers connected together. My course is not about programming, but data networks, so the connectivity is what I am looking for.
picture 1 - sample layout of GUI using Visual Studio 2015
One of the features I want to implement in my program is to show how a Master-slave, simplex connection works (i.e. the program can choose between been a master to send input from the keyboard; or slave to only receive information and print it on a textbox).
What I have already is the capability of initializing the serial port with specific characteristics (baud rate, data bits, stop bits, etc). This features are selected using combo boxes from the GUI, and assigned to the port when the user clicks a button to "open the port".
What I don't know is how to create the "slave" part of the program. My idea of what I could do is, after you choose the program to be "slave", you open the port waiting for some sort of flag or event to trigger when the input buffer has data stored.
I've been reading several forums and I can't find anything similar to what I need. I have, however, tested multiple alternatives that I believed would bring me closer to what I need with little to no result. I come to ask for an idea of what I could be doing wrong, or suggestions on how to tackle this problem. The problematic lines are bolded (or 2 stars ( * ) ):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace SerialCommTester
{
public partial class frmSerialComm : Form
{
static SerialPort _PuertoSerial;
public frmSerialComm()
{
InitializeComponent();
getAvailablePorts();
}
//---------------------------------my functions--------------------------------------
void getAvailablePorts()
{
string[] ports = SerialPort.GetPortNames();
cmbPortList.Items.AddRange(ports);
}
void activatePort()
{
//Note that all the combo boxes are named somewhat accordingly to what the information they are meant to display.
if (cmbPortList.Text != "" && cmbBaudRate.Text != "" && cmbParity.Text != "" && cmbStopBits.Text != "")
{
_PuertoSerial.PortName = cmbPortList.Text;
_PuertoSerial.BaudRate = Convert.ToInt32(cmbBaudRate.Text);
_PuertoSerial.RtsEnable = true;
_PuertoSerial.DtrEnable = true;
_PuertoSerial.DataBits = Convert.ToInt32(cmbDataBits.Text);
if (cmbParity.Text == "Even") { _PuertoSerial.Parity = Parity.Even; }
else if (cmbParity.Text == "Odd") { _PuertoSerial.Parity = Parity.Odd; }
else if (cmbParity.Text == "Space") { _PuertoSerial.Parity = Parity.Space; }
else if (cmbParity.Text == "Mark") { _PuertoSerial.Parity = Parity.Mark; }
else { _PuertoSerial.Parity = Parity.None; }
if (cmbStopBits.Text =="2") { _PuertoSerial.StopBits = StopBits.Two; }
else if (cmbStopBits.Text == "1.5") { _PuertoSerial.StopBits = StopBits.OnePointFive; }
else { _PuertoSerial.StopBits = StopBits.One; }
if (cmbHandShake.Text == "Software Flow Control") { _PuertoSerial.Handshake = Handshake.XOnXOff; }
else if (cmbHandShake.Text == "Hardware Flow Control") { _PuertoSerial.Handshake = Handshake.RequestToSend; }
else { _PuertoSerial.Handshake = Handshake.None; }
_PuertoSerial.ReadTimeout = 500;
_PuertoSerial.WriteTimeout = 500;
_PuertoSerial.Open();
//in my understanding, this line of code is needed to handle data being received. Does it trigger a flag or something?
**_PuertoSerial.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);**
}
else
{
txtRecieve.Text = "Input selection missing 1 or more characteristics";
}
}
**
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort testing = (SerialPort)sender;
txtRecieve.AppendText(testing.ReadExisting()); //txtRecieve cannot be reached within this function. It indicates the following error: "An object reference is required for the non-static field, method, or property 'frmSerialComm.txtRecieve'
}
**
void enableDisableGUI(bool[] input)
{
grpConnection.Enabled = input[0];
grpCharacteristics.Enabled = input[1];
btnOpenPort.Enabled = input[2];
btnClosePort.Enabled = input[3];
txtSend.Enabled = ((cmbControlMasterSlave.Text == "Slave") ? false : true);
}
//----------------------------C# objects / functions--------------------------------------
private void btnOpenPort_Click(object sender, EventArgs e)
{
try
{
_PuertoSerial = new SerialPort();
activatePort();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Message ", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
bool[] format = { false, false, false, true};
enableDisableGUI(format);
}
private void btnClosePort_Click(object sender, EventArgs e)
{
_PuertoSerial.Close();
bool[] format = { true, true, true, false};
enableDisableGUI(format);
}
private void txtSend_KeyPress(object sender, KeyPressEventArgs e)
{
_PuertoSerial.Write(e.KeyChar.ToString()); //this is how I send data through the serial port.
}
private void btnClearTxts_Click(object sender, EventArgs e)
{
txtRecieve.Clear();
txtSend.Clear();
}
} //class closes
} //program closes
I am not an experienced programmer, I just want to create something useful for my students. Any constructive criticism will be highly appreciated.
I don't have any definitive answers for you. You code looks like it should provide what you need once you get past the two possible glitches.
I think you should attach your SerialDataReceivedEventHandler BEFORE
you call _PuertoSerial.Open().
It may have no effect since event handlers can normally be enabled/disabled dynamically, but I base the advice on the following comment taken from the .Net source code for SerialPort on MSDN.
// all the magic happens in the call to the instance's .Open() method.
// Internally, the SerialStream constructor opens the file handle, sets the device control block and associated Win32 structures, and begins the event-watching cycle.
The "object reference" error might be resolved by removing the
static modifier from your DataReceivedHandler. If not, or if that
static modifier is necessary for some reason, then perhaps the
txtRecieve control has a private modifier which needs to be changed
to internal or public. You should be able to use Visual Studio in
debug mode to step into the InitializeComponent() method and see
where txtRecieve is being instantiated.
Well, I believe that I needed to read more. This is how I solved the problem (if this is not the real solution, at least is working for now):
I moved the "SerialDataReceivedEventHandler" line before the _PuertoSerial.open();
I followed the suggestions from this article:
https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(EHInvalidOperation.WinForms.IllegalCrossThreadCall);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true
So my funtions (one existings + a new one) look like this:
void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
printReceivedText(_PuertoSerial.ReadExisting());
}
private void printReceivedText(string text)
{
if (this.txtSend.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(printReceivedText);
this.Invoke(d, new object[] { text });
}
else
{
this.txtRecieve.AppendText(text);
_PuertoSerial.DiscardInBuffer();
}
}
For now seems to be working fine. The final testing will come when I connect another terminal and see the program interacting with each other.
I have something like :
private void Form1_Load(object sender, EventArgs e)
{
Hide();
string ngdx = "*ngdx";
string atdx = "*atdx";
for (;;)
{
try
{
string[] convertngdx = Directory.GetFiles("D:\\folder", ngdx);
string[] convertatdx = Directory.GetFiles("D:\\folder", atdx);
foreach (var convertngd in convertngdx)
{
File.Move(convertngd, Path.ChangeExtension(convertngd, ".ngd"));
}
foreach (var convertatd in convertatdx)
{
File.Move(convertatd, Path.ChangeExtension(convertatd, ".atd"));
}
}
catch
{
}
}
}
I start my app and every time a .ngdx and .atdx file is send to the folder it automatically converts it to .ngd and .atd.
My problem is that it instantly converts them , and I want it to wait for a second before converting them.
I used System.Threading.Thread.Sleep(1000); but it doesn't quite seem to work,I think because when I run my app the System.Threading.Thread.Sleep(1000); is called and then after a second it is never called again.
The idea is every time a new .ngdx or .atdx is send to the folder I want it to wait for a second before converting them.
As an alternative to using an infinite for loop (which will tie up the UI thread) you could use a FileSystemWatcher. (example)
Hi I'm trying to program a simple C# WPF that displays time information on a virtual scoreboard in real time from a timing system. I'm fairly new to programming so in depth explanation would be appreciated.
I have created a new thread to handle the incoming data from the COM port and as the app is developed this data will be interpreted. For now I just wanted to display the raw information (in hex) that is coming from the timer into a textbox. This works but not as intended. I am receiving tons of duplicate information, my only explanation is I am reading the data too slowly or its reading the same byte over and over. What I would like to happen is to take out each byte and display them, all controlled by one start/stop button.
Possible solutions include storing the entire buffer in a list or array which I'm not quite sure of yet, I don't want to add so many threads that the program freezes everything up.
Here is my code so far (I'm new to pretty much all the code I have written here, so if anything is bad practice please let me know):
public partial class MainWindow : Window
{
SerialPort comms;
Thread commThread;
bool flag;
string message;
public MainWindow()
{
InitializeComponent();
comms = new SerialPort();
}
private void PortControl_Click(object sender, RoutedEventArgs e)
{
if (!comms.IsOpen)
{
PortControl.Content = "Stop";
comms.PortName = "COM1";
comms.BaudRate = 9600;
comms.DataBits = 8;
comms.StopBits = StopBits.One;
comms.Parity = Parity.Even;
comms.ReadTimeout = 500;
comms.ReceivedBytesThreshold = 1;
commThread = new Thread(new ThreadStart(Handle));
comms.Open();
comms.DataReceived += new SerialDataReceivedEventHandler(ReadIn);
}
else
{
PortControl.Content = "Start";
flag = false;
comms.DataReceived -= ReadIn;
commThread.Join();
comms.Close();
}
}
private void ReadIn(object sender, SerialDataReceivedEventArgs e)
{
if (!commThread.IsAlive)
{
flag = true;
commThread.Start();
}
}
private void Handle()
{
while (flag)
{
if (comms.IsOpen)
{
try
{
message = comms.ReadByte().ToString("X2");
Dispatcher.BeginInvoke((Action)(() =>
{
ConsoleBox.Text += message + " ";
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
}
Here is one solution.
The serial port is receiving the data in its own thread, and you should read the incoming bytes in the data received handler.
I propose to read the data and add it to a thread-safe FIFO list in the data received handler and read the data from the list in the main thread.
See my solution in post Serial port reading + Threads or something better?