I have a pair of com ports.one of them sends data and the other one reads data. I want it to send a command (p) automatically every five seconds and wait to get the answer and read it and the sends the command again. Now it just sends the command automatically every 5 seconds. I don't know what to add to wait for the answer...
private Timer _timer;
public Form1()
{
InitializeComponent();
_timer = new Timer();
_timer.Interval = 5000;
_timer.Tick += _timer_Tick;
}
private void _timer_Tick(object sender , EventArgs e)
{
SendData();
}
private void Form1_Load(object sender, EventArgs e)
{
btnSendData.PerformClick();
}
private void btnSendData_Click(object sender, EventArgs e)
{
if (!_timer.Enabled)
{
SendData();
_timer.Enabled = true;
}
else
{
_timer.Enabled = false;
}
}
private void SendData()
{
if (serialPort1.IsOpen)
{
dataOut = "P<CR>";
serialPort1.Write(dataOut);
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
dataIn = serialPort1.ReadExisting();
this.Invoke(new EventHandler(ShowData));
}
private void ShowData(object sender, EventArgs e)
{
tBoxDataIn.Text += dataIn;
}
I think this will be helpful:
async
await
Using async to create a task and then awaiting it is the way to go i think.
Related
I am trying to increment an value in Arduino and send it on port and after that to display it in a label in real-time.
even that I put and delay(200) and Thread.sleep(200);
namespace Receiver
{
public partial class Form1 : Form
{
SerialPort port;
public Form1()
{
InitializeComponent();
this.FormClosed += new FormClosedEventHandler(Form1_FormClosed);
if (port == null)
{
port = new SerialPort("COM9", 9600);//Set your board COM
port.Open();
}
}
void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (port != null && port.IsOpen)
{
port.Close();
}
}
private void Afisare_Click(object sender, EventArgs e)
{
while (true)
{
string a = port.ReadExisting();
afisare.Text = a;
Thread.Sleep(200);
}
}
}
}
in change I got all the values, one by after one,down the screen some of them.
You are running an endless loop in your Afisare_Click handler that runs in the same thread as you UI. This means that the UI will not be able to render the control changes.
Thread.Sleep code switches the context to other threads, but not the UI thread.
Your approach should be using Timer.
public partial class Form1 : Form
{
private Timer _timer;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_timer = new Timer();
_timer.Interval = 200;
_timer.Tick += _timer_Tick;
_timer.Enabled = true;
_timer.Start();
}
private void _timer_Tick(object sender, EventArgs e)
{
// This function will be called every 200 ms.
// Read the information from port, update the UI.
string a = port.ReadExisting();
afisare.Text = a;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
_timer.Stop();
if (port != null && port.IsOpen)
{
port.Close();
}
}
}
On .NET Windows form, I have Background worker component that works fine. I have 5 forms, that has basically same Background worker on it with same code.
Can I extract this code to other class and somehow use it, considering this is an event? This is code I have on form. It takes 20 lines of code, and it would be nice if this can be refactored. Note: as you can see, I have already put it to other class BackgroundWorkerHelper, but can I also somehow refactor this events on Background worker, so that it is in other class as well, this way code is less and reused.
private void RunBackgroundWorker(string infoLabelText, int imageIndex)
{
BackgroundWorkerHelper.Run(backgroundWorker, progressBar, infoLabelText, imageIndex);
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorkerHelper.DoWork(backgroundWorker);
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
BackgroundWorkerHelper.ProgressChanged(sender, e, progressBar);
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BackgroundWorkerHelper.RunWorkerCompleted(sender, e, progressBar);
}
Note: for now I would like to avoid using user control. I know I could do it, but then you have code that handles placing user control and so on. I am still not very good in it.
Here is solution, thanks to rory who gave me idea how to do it. First, I made this class:
public class BackgroundWorkerHelper
{
private static string _infoLabelText = string.Empty;
public BackgroundWorker _BackgroundWorker;
private BarEditItem _marqueeInfo;//this is marquee progress bar
public BackgroundWorkerHelper(BarEditItem marqueeInfo)
{
_marqueeInfo = marqueeInfo;
_BackgroundWorker = new BackgroundWorker();
_BackgroundWorker.WorkerReportsProgress = true;
_BackgroundWorker.WorkerSupportsCancellation = true;
_BackgroundWorker.DoWork += backgroundWorker_DoWork;
_BackgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;
_BackgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
}
public void Run(string labelText, int imageIndex)
{
_marqueeInfo.Caption = labelText;
_marqueeInfo.ImageIndex = imageIndex;
if (!_BackgroundWorker.IsBusy)
_BackgroundWorker.RunWorkerAsync();
else
_marqueeInfo.Caption = "Busy processing saving data, please wait...";
}
public void DoWork()
{
for (int i = 0; i <= 5; i++)
{
_BackgroundWorker.ReportProgress(i); // call backgroundWorker_ProgressChanged event and pass i (which is e argument e.ProgressPercentage) to update UI controls
Thread.Sleep(250);
}
}
public void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
_marqueeInfo.Visibility = BarItemVisibility.Always;
}
public void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_marqueeInfo.Visibility = BarItemVisibility.Never;
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
DoWork();
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ProgressChanged(sender, e);
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
RunWorkerCompleted(sender, e);
}
then in FORM, in class level above constructor place
private readonly BackgroundWorkerHelper _backgroundWorkerHelper;
then in Form Constructor instantiate class
_backgroundWorkerHelper = new BackgroundWorkerHelper(marqueeInfo);
and then I just call it in my form
_backgroundWorkerHelper.Run("Saving", 14);
how can I get the value of my textbox 1seconde after the last change .
I tried with Stopwatch and TimerStamp but I just get the time between two change I don't know how to get the value of textbox 1 seconde after.
Thanks for help!
Edit:
Stopwatch TimerBetweenWrite = new Stopwatch();
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TimerBetweenWrite.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = TimerBetweenWrite.Elapsed;
if (Search.Text != null && ts.Seconds >= 1)
{
//doing my stuff
}
TimerBetweenWrite.Restart();
}
But this don't work like I want because we need to change the TextBox 1 seconde after last change. I want run a function 1 seconde after the last change of the TextBox but the user can continue to change the TextBox.
Final Edit:
That the code which work Thank's all for help!
public partial class ViewerPage : Page
{
System.Timers.Timer myTimer = new System.Timers.Timer(1000);
public ViewerPage()
{
InitializeComponent();
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
myTimer.Stop(); //Reset timer
myTimer.Start(); //Restart it
}
private void myTimer_Elapsed(Object sender, ElapsedEventArgs e)
{
ThreadContext.InvokeOnUiThread(
delegate()
{
// Doing My Stuff
myTimer.Stop();
});
}
}
public static class ThreadContext
{
public static void InvokeOnUiThread(Action action)
{
if (Application.Current.Dispatcher.CheckAccess())
{
action();
}
else
{
Application.Current.Dispatcher.Invoke(action);
}
}
public static void BeginInvokeOnUiThread(Action action)
{
if (Application.Current.Dispatcher.CheckAccess())
{
action();
}
else
{
Application.Current.Dispatcher.BeginInvoke(action);
}
}
}
Timer myTimer = new Timer(1000);
myTimer.Elapsed += myTimer_Elapsed;
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
myTimer.Stop(); //Reset timer
myTimer.Start(); //Restart it
}
private void myTimer_Elapsed(Object sender, ElapsedEventArgs e)
{
//Do your stuff
}
Explanation: Each time the text changes, the timer gets reset and started again. It will only tick if it's enabled (aka not stopped by the TextChanged event) for a second.
If you want it to tick only once and then stop, set the AutoReset property to true.
You could inherit from TextBox and raise your own StableTextChanged event. The new control will appear at the top of your ToolBox:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void textBoxEx1_StableTextChanged(object sender, EventArgs e)
{
label1.Text = ((TextBoxEx)sender).Text;
}
}
public class TextBoxEx : TextBox
{
public event dlgStableTextChanged StableTextChanged;
public delegate void dlgStableTextChanged(object sender, EventArgs e);
private System.Windows.Forms.Timer tmr;
public TextBoxEx()
{
tmr = new System.Windows.Forms.Timer();
tmr.Interval = 1000;
tmr.Tick += Tmr_Tick;
this.TextChanged += TextBoxEx_TextChanged;
}
private void Tmr_Tick(object sender, EventArgs e)
{
tmr.Stop();
if (this.StableTextChanged != null)
{
this.StableTextChanged(this, new EventArgs());
}
}
private void TextBoxEx_TextChanged(object sender, EventArgs e)
{
tmr.Stop();
tmr.Start();
}
}
I have a Form where one can Sign In and it could take a while till the data gets loaded into the Form. So I wanted to create a seperate Form (loadScreen.cs) with a Progress Bar when the Form is loading. I tried this in the loadScreen.cs Form:
private void Form1_Load(object sender, EventArgs e)
{
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged +=
new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
int percentFinished = (int)e.Argument;
while (!worker.CancellationPending && percentFinished < 100)
{
percentFinished++;
worker.ReportProgress(percentFinished);
System.Threading.Thread.Sleep(50);
}
e.Result = percentFinished;
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.Close();
}
I've read that the worker_DoWork method should have the code which takes longer to load. I don't know how to handle this since my button is in Form1. When it's clicked then I go to another class with
private void signIn_Click(object sender, EventArgs e)
{
var logIn = new LogIn(this);
logIn.checkUserInput(this);
}
and there I execute the operations which load certain things. How to connect everything? I need help!
I'm actually in the process of creating a general-purpose dialogue for this sort of thing. It's not going to be ready in time to be of use to you but I would suggest that you go along similar lines. Create your "Loading" dialogue so that it accepts a delegate and invokes it in the DoWork event handler. The main form can then contain a method that does the work and you can pass a delegate for that method to the dialogue. I'll post a very basic example.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private DataTable table;
private void button1_Click(object sender, EventArgs e)
{
var work = new Action(GetData);
using (var f2 = new Form2(work))
{
f2.ShowDialog();
this.dataGridView1.DataSource = this.table;
}
}
private void GetData()
{
this.table = new DataTable();
using (var adapter = new SqlDataAdapter("SELECT * FROM MyTable", "connectionstring here"))
{
adapter.Fill(table);
}
}
}
public partial class Form2 : Form
{
private Action work;
public Form2(Action work)
{
InitializeComponent();
this.work = work;
}
private void Form2_Load(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
this.work();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.DialogResult = DialogResult.OK;
}
}
Note that there's no real way to measure progress when using a data adapter so you could only really display a marquee progress bar in this case.
Hi all I have used timer class to call an event after a minute here is my code
public partial class TimerScheduler : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
}
System.Timers.Timer _timer = new System.Timers.Timer(10000);
protected void Button1_Click(object sender, EventArgs e)
{
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true;
}
protected void Button2_Click(object sender, EventArgs e)
{
_timer.Stop();
_timer.Enabled=false;
}
}
but as I click start button timer works fine and after every minute it gets called but as I try to stop it it does not work And the _timer_Elapsed events gets called after every 1 minute
Edit the code as below
public partial class TimerScheduler : System.Web.UI.Page
{
System.Timers.Timer _timer = new System.Timers.Timer(10000);
protected void Page_Load(object sender, EventArgs e)
{
_timer.Elapsed -= new ElapsedEventHandler(_timer_Elapsed); //to avoid multiple linking of event
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
_timer.Enabled = true;
}
protected void Button2_Click(object sender, EventArgs e)
{
_timer.Enabled=false;
}
}
You could easily make the timer fire only once by setting AutoReset = false. Then you'd have to restart the timer manually in the timer's event handler.
System.Timers.Timer _timer = new System.Timers.Timer(1000);
bool timerStarted = false;
protected void Button1_Click(object sender, EventArgs e)
{
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true;
_timer.AutoReset = false;
timerStarted = true;
}
protected void Button2_Click(object sender, EventArgs e)
{
timerStarted = false;
_timer.Enabled=false;
}
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
_timer.Enabled = timerStarted;
}
Oh, and by the way: I don't know what you're trying to achieve, but an ASP.NET page is not something that runs for a longer time. The code is executed once on the server and the HTML is passed back to the client. So what you want may not work at all.
You just Subscribe to the ElapsedEvent outside the Button1_Click event handler and start the Timer in Button1_Click event handler.
System.Timers.Timer _timer = new System.Timers.Timer(10000);
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
protected void Button1_Click(object sender, EventArgs e)
{
_timer.Start();
}
protected void Button2_Click(object sender, EventArgs e)
{
_timer.Stop();
}