I have a site that is extremely basic and will only ever consist of a single integer.
However the integer will actively change, I want to add onto my existing application to display what this integer is in real time.
-I've tried using a Timer and WebClient however if I put the code under InitializeComponent() the form will never load.
-Also if I put the code in Form1_Load the form will never load.
-I was successful in getting the number to display in real time by putting the code under a button_click event, but I want this code to begin as soon as the form load.
-Also when the button was first clicked the first timer sequence the label would display lat (unsure what this means)
-After the button was pressed and the timer loop began the app breaks, the number will update properly, but you cannot use any other functionality of the app, you can not move the window, you cannot close the app, etc..
private void timer_Tick(object sender, EventArgs e)
{
Timer timer = (Timer)sender;
this.Visible = false;
timer.Stop();
this.Visible = true;
}
private void button1_Click(object sender, EventArgs e)
{
int c = 5;
while (c == 5)
{
using (var client = new WebClient())
{
var s = client.DownloadString(#"myURL.html");
var htmldoc2 = (IHTMLDocument2)new HTMLDocument();
htmldoc2.write(s);
var plainText = htmldoc2.body.outerText;
label1.Text = plainText;
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = 5000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
}
}
Please help me no clue what I am doing wrong here
I managed to fix my issue by using the following code if anyone ever has a similar question:
private void test()
{
using (var client = new WebClient())
{
var s = client.DownloadString(#"myURL.html");
var htmldoc2 = (IHTMLDocument2)new HTMLDocument();
htmldoc2.write(s);
var plainText = htmldoc2.body.outerText;
label1.Text = plainText;
}
}
int i = 1;
private void timer1_Tick(object sender, EventArgs e)
{
i += 1;
if (i >= 199)
{
i = 1;
timer1.Stop();
timer1.Start();
}
test();
}
timer1 was added to the winform from the toolbox, and is set to enabled with an interval of 200
Related
I'm trying to develop an application to convert text to morse code and vice versa. I just managed to do the first phase completely which means when you type a character you will see the encoded type of that character.
but in the second phase I got some problem:
here is my code:(hint:sw=first stopwatch,flagsw=second stopwatch,datas=dataset,dbc=databaseconverter,listofcode=string of '.' and '-')
private void txtletters_KeyDown(object sender, KeyEventArgs e)
{
txtletters.BackColor = Color.Yellow;
sw.Start();
if (flagsw.ElapsedMilliseconds > 400)
{
datas = dbc.srchfortext(listofcode);
lbltext.DataBindings.Clear();
lbltext.DataBindings.Add("text", datas, "t.letter");
txtletters.Text += lbltext.Text;
listofcode = "";
}
flagsw.Reset();
}
private void txtletters_KeyUp(object sender, KeyEventArgs e)
{
txtletters.BackColor = Color.White;
sw.Stop();
if (sw.ElapsedMilliseconds < 250)
listofcode += ".";
else
listofcode += "-";
sw.Reset();
flagsw.Start();
}
I just managed to do the work somehow but as the code shown:
when you press any key first timer will start and first timer determine if it is . or -
when you release it second timer will start (with that timer I want to know if the string of '.','-' should be closed and send to database to return the specified character...the problem in here is that the application won't end the timer and return the char unless I preform a keydown again and that means I'm not gonna see the char i typed unless I press another key(just don't tell me it's because that the second timer is in keydown, I had to do that cause I didn't have any other choice...But at least I know the Idea but don't know how to implement it...I just need somebody to help me implement it...)
I need that second timer works in background when a keydown occurred it will reset and when a keyup occurred(means that key released)it will start again. whenever second timer(flagsw.ElapsedMilliseconds > 400)got bigger than that time it will do the job and clear the string for next use.
First I have to thanks to Chris...with your answer I got the idea and found the way...
It's now fully implemented and works here is my code if anybody else wants to use...(it's just the decoder part of the morse project)
namespace Morse_Code
{
public partial class frmdecdotmode : Form
{
Boolean flag_isdown = false;
Stopwatch sw = new Stopwatch();
Timer morse_timer = new Timer();
string listofcode;
DataSet datas = new DataSet();
DataBaseController dbc = new DataBaseController();
public frmdecdotmode()
{
InitializeComponent();
}
private void frmdecdotmode_FormClosing(object sender, FormClosingEventArgs e)
{
MainMenu mm = new MainMenu();
mm.Show();
this.Hide();
}
private void txtletters_KeyDown(object sender, KeyEventArgs e)
{
flag_isdown = true;
txtletters.BackColor = Color.Yellow;
sw.Start();
morse_timer.Stop();
}
private void txtletters_KeyUp(object sender, KeyEventArgs e)
{
flag_isdown = false;
txtletters.BackColor = Color.White;
sw.Stop();
if (sw.ElapsedMilliseconds < 250)
listofcode += ".";
else
listofcode += "-";
sw.Reset();
morse_timer.Start();
}
private void frmdecdotmode_Load(object sender, EventArgs e)
{
morse_timer.Interval = 1000;
morse_timer.Enabled = true;
morse_timer.Tick += morse_timer_Tick;
}
private void morse_timer_Tick(object sender, EventArgs e)
{
if (flag_isdown == false && listofcode != null)
{
datas = dbc.srchfortext(listofcode);
lbltext.DataBindings.Clear();
lbltext.DataBindings.Add("text", datas, "t.letter");
txtletters.Text += lbltext.Text;
listofcode = "";
}
}
}
}
Thanks to every body who helped me do this...
Ya Ali(a.s)
so I am new to WPF and am just trying to make a simple little program. When you hit a start button it will continuosly print fake code until you hit a stop button. I have tried to make it repeat until the stop button is hit 10 different ways but none of them are working. The TextBlock element will update once (or never) and then the whole program becomes unusable and the loading cursor comes up. I would guess that instead of going through a cycle, and then updating the TextBlocks, it is doing everything in the background and not updating visually.
public partial class MainWindow : Window
{
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
Random r1 = new Random();
bool stop = false;
int numUse
public MainWindow()
{
InitializeComponent();
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
}
//Executes when the start button is hit, begins timer
private void Button_Click(object sender, RoutedEventArgs e)
{
do
{
dispatcherTimer.Tick += dispatcherTimer_Tick;
} while (stop == false);
}
//Executes when the stop button is hit, ends timers do while loop
private void Button_Click_1(object sender, RoutedEventArgs e)
{
stop = true;
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
numUse = r1.Next(1, 2);
if (numUse == 1)
{
CodeBlock1.Text = "struct group_info init_groups = { .usage = ATOMIC_INIT(2) }; ";
CodeBlock2.Text = "";
CodeBlock3.Text = "struct group_info *groups_alloc(int gidsetsize){ ";
CodeBlock4.Text = "struct group_info *group_info; ";
CodeBlock5.Text = "int nblocks; ";
CodeBlock6.Text = "int i; ";
CodeBlock7.Text = "";
CodeBlock8.Text = "initialize stream";
}
else if (numUse == 2)
{
CodeBlock1.Text = "if (gidsetsize <= NGROUPS_SMALL) ";
CodeBlock2.Text = "group_info->blocks[0] = group_info->small_block; ";
CodeBlock3.Text = " else { ";
CodeBlock4.Text = " for (i = 0; i < nblocks; i++) { ";
CodeBlock5.Text = "b = (void *)__get_free_page(GFP_USER); ";
CodeBlock6.Text = " goto out_undo_partial_alloc; ";
CodeBlock7.Text = "} ";
CodeBlock8.Text = "";
} else
{
}
}
}
}
I have tried for loops, do while, using different methods in different orders. I understand that I likely messed up while going those routes so any method is ok for my purposes. Obviously I am using a Timer in this case.
It is not necessary to repeatedly call dispatcherTimer.Tick += dispatcherTimer_Tick in the while loop of Button_Click. I suspect that while this loop is running, nothing else on the message pump will run, including ticks from the DispatcherTimer.
You could probably do away with stop and merely act on the DispatcherTimer directly by calling Stop() from anywhere in the code.
Perhaps this instead:
public MainWindow()
{
InitializeComponent();
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Tick += dispatcherTimer_Tick; // set it up here
}
//Executes when the start button is hit, begins timer
private void Button_Click(object sender, RoutedEventArgs e)
{
dispatcherTimer.Start(); // start timer
}
//Executes when the stop button is hit, ends timers do while loop
private void Button_Click_1(object sender, RoutedEventArgs e)
{
dispatcherTimer.Stop(); // stop timer
}
I have a Windows Forms App written in C#. The idea is, that it draws a chart for 10 numbers after clicking a button. This works fine. I click the button, and I get a nice chart. However I also want to include a sort of "auto refresh" mode, where the chart is refreshed every few seconds. This would be enabled via Checkbox. Here's my code:
private void chartButton_Click(object sender, EventArgs e) //draw a chart after the button is clicked
{
Random rdn1 = new Random();
int value;
foreach (var series in ekran.Series) //clear previous values
{
series.Points.Clear();
}
for (int i = 0; i < 10; i++) //draw a chart from ten new values
{
value = rdn1.Next(0, 10); //for testing purpouses the value will be a random number a random number
ekran.Series["seria1"].Points.AddXY(i, value);
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
while(checkBox1.Checked) //click the chartButton every one second, when the checkbox is checked
{
//rysuj.PerformClick();
chartButton.PerformClick();
Thread.Sleep(1000);
}
}
And now for my problem. When I check the Checkbox, I will not get a chart until it finishes every iteration of the while loop. Since it's an infinite loop, I will never get my chart. If I rewrite the code to make only five iterations when the Checkbox is checked, I only get the chart for the fifth one (and after five seconds, as to be expected).
So my question is: how can I force this to draw a chart every time the button is clicked via chartButton.PerformClick()? When I click the button manually, everything works fine, it's just when I try to do it automatically, I get my problem.
EDIT
First of all,thank you for the replies. However, I'm still experiencing the same problem when using a timer. This is how my code looks now:
namespace ChartTest
{
public partial class Form1 : Form
{
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 1000;
}
void timer_Tick(object sender, EventArgs e)
{
timer.Enabled = false;
chartButton.PerformClick();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
while (checkBox1.Checked)
{
timer.Enabled = true; // Enable the timer
timer.Start(); // Start the timer
}
}
private void chartButton_Click(object sender, EventArgs e) //draw a chart after the button is clicked
{
Random rdn1 = new Random();
int value;
ekran.Series.Clear();
var series2 = new System.Windows.Forms.DataVisualization.Charting.Series
{
Name = "Series2",
Color = System.Drawing.Color.Green,
IsVisibleInLegend = false,
IsXValueIndexed = true,
ChartType = SeriesChartType.Line
};
this.ekran.Series.Add(series2);
for (int i = 0; i < 100; i++)
{
value = rdn1.Next(0, 10);
series2.Points.AddXY(i, value);
}
}
}
}
Sorry for being a total noob, but I have no idea, what am I doing wrong this time.
This is exactly what a Timer is for. Have the checkbox start/stop or enable/disable the timer, and handle the Timer.Tick event to redraw your chart. In your case, the event handler could simply call chartButton.PerformClick(), or insert whatever code the PerformClick() does.
ETA: If the chart refresh is not instant, you will probably want to push it off to a separate thread. If it's instant, there's not really any need to deal with the threading though.
I would go the route of using a thread with combination of checkbox's checkChange() event. Essentially this will allow your application to keep running while the update code will execute periodically. The refresh is determined by the sleep time, not your manual click or any other value.. Example below on how I to do this:
Thread refreshThread = null;
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (refreshThread == null) //No thread running, assume it starts this way
{
refreshThread = new Thread(chartRefresh);
refreshThread.Start();
}
else //Thread is running, must terminate
{
refreshThread.Abort();
refreshThread = null;
}
}
private void chartRefresh()
{
while (true)
{
//code to refresh chart
Thread.Sleep(10000);
}
}
Basically, I've got multiple button in my Form, and I want for it show a Stopwatch in the button.Text when the button is pressed. (Button is modified to be a toggle button.) and to stop and reset the timmer when the button is toggled off. Simple enough it seemed but because I have multiple buttons that could be pressed in any order, and I don't know anything about threading, this seems to be much more difficult that I presumed.
My origional intent was to have a function that constantly runs every second and interates a interager only if the button is pressed using this code:
public void Jogger()//purpose is to step up time[0] every second only when a button is on.
{
while (true)
{
for (int i = 0; i < 16; i++)
{
if (btnstat[i])
time[i]++;
}
Thread.Sleep(1000);
}
}
Problem is, I don't know threading so when I call the function, its stuck doing this and only this.
Either way, once this is called, all i do us call my update function that updates all the buttons including the button.Text which displays the time[0]; (array built around buttons)
Is their a better way of doing this that doesn't cause so much CPU use and/or simply works?
Thanks for all the help!
-John Ivey
Assuming you using checkbox with property Button = Appearence, in event handler for CheckedChanged:
private void CheckBoxCheckedChanged(object sender, EventArgs e)
{
CheckBox checkBox = (CheckBox) sender;
if (checkBox.Checked)
{
Timer timer = new Timer {Interval = 1000};
timer.Tick += Jogger;
timer.Start();
timer.Tag = new CheckboxCounter {CheckBox = checkBox, Time = 0};
checkBox.Tag = timer;
}
else
{
Timer timer = checkBox.Tag as Timer;
if (timer != null)
{
timer.Tag = null;
timer.Stop();
timer.Dispose();
checkBox.Tag = null;
}
}
}
Change your Jogger function:
private void Jogger(object a_sender, EventArgs a_eventArgs)
{
Timer timer = (Timer) a_sender;
CheckboxCounter data = (CheckboxCounter)timer.Tag;
data.Time++;
data.CheckBox.Text = data.Time.ToString();
}
You also need some simple class to store checkbox and current time:
class CheckboxCounter
{
public CheckBox CheckBox;
public int Time;
}
Then you can add any number of checkboxes and just set event CheckedChanged to CheckBoxCheckedChanged.
Try this out. After re-building or running, you should have the new "ButtonTimer" at the top of your ToolBox. Drop a couple on your Form, run it, and see what happens when you click them. Right click them to "Reset" them:
public class ButtonTimer : CheckBox
{
private System.Windows.Forms.Timer Tmr = new System.Windows.Forms.Timer();
private System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch();
public ButtonTimer()
{
this.Tmr.Interval = 500;
this.Tmr.Tick += new EventHandler(tmr_Tick);
this.Appearance = System.Windows.Forms.Appearance.Button;
this.CheckedChanged += new EventHandler(ButtonTimer_CheckedChanged);
ContextMenuStrip cms = new ContextMenuStrip();
ToolStripItem tsi = cms.Items.Add("Reset");
tsi.Click += new EventHandler(tsi_Click);
this.ContextMenuStrip = cms;
}
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
this.Text = TimeSpan.Zero.ToString(#"hh\:mm\:ss");
}
private void ButtonTimer_CheckedChanged(object sender, EventArgs e)
{
if (this.Checked)
{
this.SW.Start();
this.Tmr.Start();
}
else
{
this.SW.Stop();
this.Tmr.Stop();
}
}
private void tmr_Tick(object sender, EventArgs e)
{
this.UpdateTime();
}
private void UpdateTime()
{
this.Text = this.SW.Elapsed.ToString(#"hh\:mm\:ss");
}
private void tsi_Click(object sender, EventArgs e)
{
if (this.SW.IsRunning)
{
SW.Restart();
}
else
{
SW.Reset();
}
this.UpdateTime();
}
}
Application.DoEvents() for simplicity put inside loop . . but it is advisable to start to lean threading . you will just learn how to start thread and how make cross thread safe call
Next simple will be to use backgroundworker . look this http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
ok here is thread solution also as you wanted . Tested too . as a stop variable i used Tag. But u can inherit button to make state button.it be more clear way . And below code will use one thread per button . So u should make it in one thread to make it better solution . You can modify this code to do all checkings inside one thread . For this you start thread once can make delegate for attaching dinamically count function for each button or you can pass buttons before . With one word there are more than one way to do it. Good luck
this.button1.Click += new System.EventHandler(this.button_Click);
this.button2.Click += new System.EventHandler(this.button_Click);
...and so on
private void button_Click(object sender, EventArgs e)
{
Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
x.Start(sender);
}
private void button_Click(object sender, EventArgs e)
{
Button mybtn=sender as Button;
if((string)mybtn.Tag=="start"){
mybtn.Tag ="";
return;
}
mybtn.Tag = "start";
Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
x.Start(sender);
}
private bool setResult(object obj,string text)
{
if (this.textBox1.InvokeRequired)
{
Func<Button,string, bool > d = new Func<Button,string,bool >(setResult);
return (bool)this.Invoke(d,obj,text);
}
else
{
Button btn=obj as Button;
if (btn != null)
{
btn.Text = text;
if ((string)btn.Tag !="start") return false;
}
return true;
}
}
private void Jogger2(object mybtn)
{
int ii = 0;
while (true)
{
Thread.Sleep(1000);
//replace with your code
ii += 1;
if (!setResult(mybtn, ii.ToString())) break;
}
}
I'm working on a windows forms app where I have several so called "services" that poll data from various services like Twitter, Facebook, Weather, Finance. Now each of my services has its individual polling interval setting so I was thinking I could implement a System.Windows.Forms.Timer for each of my services and set its Interval property accordingly so that each timer would fire an event at the preset interval that will cause the service to pull new data preferably async through a BackgroundWorker.
Is this the best way to do it? or will it slow down my app causing performance issues. Is there a better way of doing it?
Thanks!
You can do it with one Timer, just needs smarter approach to interval:
public partial class Form1 : Form
{
int facebookInterval = 5; //5 sec
int twitterInterval = 7; //7 sec
public Form1()
{
InitializeComponent();
Timer t = new Timer();
t.Interval = 1000; //1 sec
t.Tick += new EventHandler(t_Tick);
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
facebookInterval--;
twitterInterval--;
if (facebookInterval == 0)
{
MessageBox.Show("Getting FB data");
facebookInterval = 5; //reset to base value
}
if (twitterInterval == 0)
{
MessageBox.Show("Getting Twitter data");
twitterInterval = 7; //reset to base value
}
}
}
you do not really need BackgroundWorker, as WebClient class has Async methods.
so you may simply have one WebClient object for each of your "service" and use code like this:
facebookClient = new WebClient();
facebookClient.DownloadStringCompleted += FacebookDownloadComplete;
twitterClient = new WebClient();
twitterClient.DownloadStringCompleted += TwitterDownloadComplete;
private void FacebookDownloadComplete(Object sender, DownloadStringCompletedEventArgs e)
{
if (!e.Cancelled && e.Error == null)
{
string str = (string)e.Result;
DisplayFacebookContent(str);
}
}
private void OnFacebookTimer(object sender, ElapsedEventArgs e)
{
if( facebookClient.IsBusy)
facebookClient.CancelAsync(); // long time should have passed, better cancel
facebookClient.DownloadStringAsync(facebookUri);
}