I have this simple program :
private static System.Timers.Timer t3;
private void button1_Click(object sender, EventArgs e)
{
t3 = new System.Timers.Timer(5000);
t3.AutoReset = true; t3.Enabled = true; t3.Elapsed += OnTimedEvent3;
}
private void OnTimedEvent3(Object source, ElapsedEventArgs e)
{
// MessageBox.Show("event raised");
richTextBox1.Text = "t3 is elapsed ";//
}
PROBLEM : : Nothing appears in the richTextBox1 after event is fired ! I have tried MessageBox and that works fine . what could be the problem ??
Your problem is the following:
The eventhandler of your timer is running on a different thread like your UI. You need to invoke the control like
if(richTextBox1.InvokeRequired == true)
{
richTextBox1.Invoke((MethodInvoker)delegate
{
richTextBox1.Text = "t3 is elapsed "
});
}
else
{
richTextBox1.Text = "t3 is elapsed ";
}
to access it correctly. Thats because UI objects are related to their thread. Creating a MessageBox for example is possible out of every thread - because your Box is not existing already.
Related
I have a little application contains a start and reset button in this
timer alike program.
In the button start event handler, I have a FileSystemWatcher and Timer
to call a function at certain time.
I also have another timer to count down the time call timerCounter just to do for visual aid.
What I want is to click the start button again to run the program
after the stop/reset button is clicked, but fail to do so.
Below is my part of the code that I have doubt how to restart the program again on the start button click event.
private void btnStart_Click(object sender, EventArgs e)
{
// file system watcher, timer and one other function inside this event handler
_timeLeft = (int)numUpDown.Value;
timerCounter.Start();
}
private void btnStop_Click(object sender, EventArgs e)
{
_timer.Stop();
timerCounter.Stop();
_timer.Dispose();
numUpDown.Value = 0;
timeLabel.Text = 0 + #" seconds";
lblResult.Text = #"Program has stopped, press start button to
process again.";
_fsw.Dispose();
}
private void timerCounter_Tick(object sender, EventArgs e)
{
if (_timeLeft > 0)
{
_timeLeft = _timeLeft - 1;
timeLabel.Text = _timeLeft + " seconds";
lblResult.Text = $#"Process began and counting down {timeLabel.Text} in seconds";
}
else
{
timerCounter.Stop();
timerCounter.Enabled = false;
timeLabel.Text = $#"Time's up";
}
}
I'm trying to make a label refresh every second so the countdown updates, having some trouble. I'm extremely new to C# apologies for the noob questions.
private void Form1_Load(object sender, EventArgs e)
{
bool ephCD = true;
int ephHours = (DateTime.Today.AddDays(1) - DateTime.Now).Hours;
int ephMinu = (DateTime.Today.AddDays(1) - DateTime.Now).Minutes;
int ephSecs = (DateTime.Today.AddDays(1) - DateTime.Now).Seconds;
label1.Text = ephHours.ToString() + ":" + ephMinu.ToString() + ":" + ephSecs.ToString();
while (ephCD == true)
{
label1.Refresh();
}
}
When launching this the program doesn't even appear.
Why does the program not appear?
You are performing an infinite loop in Form_Load. This means that the form will never finish loading, and your program will be stuck.
Your refresh loop needs to be on a separate thread, or ideally toss the loop and use a Timer instead of spin locking the CPU on an infinite loop.
Timer myTimer = new Timer(1000);
void Form1_Load()
{
myTimer.Elapsed += UpdateLabel;
myTimer.Start();
}
private void UpdateLabel(object sender, ElapsedEventArgs e)
{
//Update label here
}
Updating the label in a while statement is not a good option, a better approach would be to use Timer class
var aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += OnTimedEvent;
aTimer.Enabled = true;
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
//update the label
}
This will do, just copy and paste:
private void Form1_Load(object sender, EventArgs e)
{
// To update the first time.
label1.Text = (DateTime.Today.AddDays(1)- DateTime.Now).ToString(#"hh\:mm\:ss");
var timer = new Timer {Interval = 1000};
timer.Tick += (o, args) =>
{
label1.Text = (DateTime.Today.AddDays(1)- DateTime.Now).ToString(#"hh\:mm\:ss");
};
timer.Start();
}
I ended up with this simpler solution:
<script>
var myTimer = setInterval(Atualizar, 20000);
function Atualizar() {
__doPostBack('UpdatePanelNew', '');
}
</script>
Make sure you wrap what you want to update within an UpdatePanel.
This code will request a postback in every 20s. So in the code behind I can do this:
protected void Page_Load(object sender, EventArgs e)
{
myLabel.InnerText = GetInDatabaseTheValueIwant();
}
I have wcf servise that Update db it is takes 10-15 sec,and i wont to run/show my form with loading/waitting statusbar while servise working, and when service is finished i need to close the watting form.
My problem is when i run ShowDialog(); it is get stuck on it , and don't go to my service.
What i doing wrong here?
My code
My function
public static void UpdateSNXRATES(object sender, EventArgs e)
{
WaitForm waitF = new WaitForm();
waitF.ShowDialog();//here it stuck
using (var Server = new ServiceReference.Service1Client())
{
Server.ClientCredentials.Windows.ClientCredential.Domain = strDomain;
Server.ClientCredentials.Windows.ClientCredential.UserName = strUser;
Server.ClientCredentials.Windows.ClientCredential.Password = strPassword;
success=Server.UpdateSNXRATES();
}
waitF.Close();
}
My WaitForm code
public partial class WaitForm : Form
{
public WaitForm()
{
InitializeComponent();
}
private void WaitForm_Load(object sender, EventArgs e)
{
radWaitingBar1.StartWaiting();
radWaitingBar1.WaitingSpeed = 100;
radWaitingBar1.WaitingStep = 5;
}
}
ShowDialog() is a blocking call, i.e. the current thread will keep waiting on this line until the form is closed (by the user). You should show your WaitForm on a different thread than the main application thread, combined with Invoke() call to ensure that you don't do illegal cross-thread operations. You can use BackgroundWorker component to load and show your WaitForm on a different thread.
Alternately and preferably, you should move your service initialization and running code to the BackgroundWorker. That will ensure you don't need any Invokes.
Example
ServiceReference.Service1Client Server;
WaitForm waitF;
public static void UpdateSNXRATES(object sender, EventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.RunWorkerAsync();
waitF = new WaitForm();
waitF.ShowDialog();
}
static void bw_DoWork(object sender, DoWorkEventArgs e)
{
Server = new ServiceReference.Service1Client();
Server.ClientCredentials.Windows.ClientCredential.Domain = strDomain;
Server.ClientCredentials.Windows.ClientCredential.UserName = strUser;
Server.ClientCredentials.Windows.ClientCredential.Password = strPassword;
success = Server.UpdateSNXRATES();
}
static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
waitF.Close()
}
i cant get the progress bar to work! if i execute the following code the bar remains empty even if the code gets executed the ReportProgress doesnt seem to update anything..:
namespace GPUZ_2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
GPUZdata test = new GPUZdata
{
};
//invio l'oggetto al thread backgroundworker
backgroundWorker1.RunWorkerAsync(test);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//
// e.Argument always contains whatever was sent to the background worker
// in RunWorkerAsync. We can simply cast it to its original type.
//
GPUZdata argumentTest = e.Argument as GPUZdata;
argumentTest.OneValue = 6;
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(50);
argumentTest.TwoValue = 3;
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(100);
//
// Now, return the values we generated in this method.
// Always use e.Result.
//
e.Result = argumentTest;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Receive the result from DoWork, and display it.
GPUZdata test = e.Result as GPUZdata;
this.Text = test.OneValue.ToString() + " " + test.TwoValue.ToString();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Change the value of the ProgressBar to the BackgroundWorker progress.
progressBar1.Value = e.ProgressPercentage;
// Set the text.
this.Text = e.ProgressPercentage.ToString();
}
}
}
thanks in advance for your help
To initialize the BackgroundWorker, you must enable progress reporting and hook up your event handlers:
// Enable progress reporting
backgroundWorker1.WorkerReportsProgress = true;
// Hook up event handlers
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
I don't see where you set the WorkerReportsProgress property to true - that most likely is the problem:
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.RunWorkerAsync(test);
I had the same problem. In AssemblyInfo.cs you should make this change for ComVisible.
[assembly: ComVisible(true)]
I am setting the .Text value of a textbox, disabling it, and then calling a BackgroundWorker to do a lengthy filesystem operation. The textbox does not update with the new text value until about halfway through the BackgroundWorker operation.
What can I do to force the texbox to show the new text value ASAP? Relevant code below:
void BeginCacheCandidates()
{
textBox1.Text = "Indexing..."; // <-- this does not update until about 20 to 30 seconds later
textBox1.Enabled = false;
backgroundWorker1.RunWorkerAsync();
}
void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
//prime the cache
CacheCandidates(candidatesCacheFileName);
}
void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
textBox1.Text = "";
textBox1.Enabled = true;
textBox1.Focus();
}
Update: I resolved the issue. It was code unrelated to this - I had overridden WndProc and it was going into a loop...
Unless there's some detail I'm missing, wouldn't ReportProgress give you what you want?
void BeginCacheCandidates()
{
textBox1.Text = "Indexing...";
textBox1.Enabled = false;
backgroundWorker1.ReportProgress += new ProgressChangedEventHandler(handleProgress)
backgroundWorker1.RunWorkerAsync();
}
void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
//prime the cache
backgroundWorker1.ReportProgress(<some int>, <text to update>);
CacheCandidates(candidatesCacheFileName);
}
void handleProgress(object sender, ProgressChangedEventArgs e)
{
...
textBox1.Text = e.UserState as String;
...
}
Try invoking the change on the textbox instead of directly calling it.
textBox1.BeginInvoke(new MethodInvoker(() => { textBox1.Text = string.Empty; }));
This will cause the change to happen on the Form's thread.
Use Form.Update() method to force UI updates.
void BeginCacheCandidates()
{
textBox1.Text = "Indexing..."; // <-- this does not update until about 20 to 30 seconds later
textBox1.Enabled = false;
this.Update(); // Force update UI
backgroundWorker1.RunWorkerAsync();
}