I have a code in which I have started a timer tick event of 75 sec. The application is supposed to perform a task, at a time interval of 75 sec. The application just runs fine sometimes for 5 hrs, however all of a sudden it shows not responding...whenever other operations are done on the computer like opening other files...
My code looks like this:
private void button2_Click(object sender, EventArgs e)
{
tmrTimer.Enabled = true;
}
private void tmrTimer_Tick(object sender, EventArgs e)
{
//Do my stuff here;
}
I think it maybe because you used Timer from System.Windows.Forms.Timer class. This kind of Timers are Single Thread Timers; which means they use the same thread that your UI use. So, it's obvious why your application shows not responding when the thread has lots of things to do.
I suggest to change the timer type and try this one: System.Threading.Timers.
Related
I can't stop my app because I have a while loop, so the gui doesn't let me click the stop button, it looks something like:
private void btnStart_Click(object sender, EventArgs e)
{ while(true)
{
//some code here
}
}
//some methods here
private void btnStop_Click(object sender, EventArgs e)
{
Application.Exit();
}
Firstly if you're running some sort of long running background job then you should not be doing that in the UI thread, because as you state, you cannot then do anything else in the UI thread to stop the loop. You'll need to defer that work to a secondary thread, or a timer, or something outside of the context of the UI thread. You can Google many different ways to achieve this.
Secondly, if you need to stop the loop then change the while condition for the loop from true to some other monitorable condition, e.g. a variable called keepRunning, which you can then set from within the btnStop_Click method. Of course if you adopt my advice in the first point then there may be some other way to stop the loop from running, e.g. if it's a timer then you can stop that timer in the appropriate way.
Thirdly, you should wait for the background operation to stop before closing the application.
I am using C#,.Net4.0 and Visual Studio 2010 and I am trying to get this behaviour from my windows form application when the user click on a button:
A GUI LED starts to blink
A long rung operation starts
When the operation at point 2 ends the LED stops blinking
private void Btn_WebService_Click(object sender, EventArgs e)
{
Thread_Blink = new Thread(() => { LED_Blink(LED.WS); });
Thread_Blink.Start();
// Do something that takes time.. Let's imulate with a sleep
Thread.Sleep(2000);
Thread_Blink.Abort();
}
I also tried using 3 different events and/or timers..
private void Btn_WebService_MouseDown(object sender, MouseEventArgs e)
{
Timer_Blink.Enabled = true;
}
private void Btn_WebService_Click(object sender, EventArgs e)
{
// Do something that takes time.. Let's imulate with a sleep
Thread.Sleep(2000);
}
private void Btn_WebService_MouseUp(object sender, MouseEventArgs e)
{
Timer_Blink.Enabled = false;
}
The result is always the same: The LED starts to blink only AT THE END of the long running operation (Thread.Sleep(2000);) and suddenly STOPS so that you can't see anything. Why does this happen and how can I get the desired behaviour?
I add further infos. I tried to use BackgroundWorked and implemented the wanted behavour in this way:
private void Btn_WebService_Click(object sender, EventArgs e)
{
BlinkWorker.RunWorkerAsync(LED.WS);
LedOn(LED.WS);
TestWebService(); // This method takes about 2 seconds to answer..
LedOff(LED.WS);
BlinkWorker.CancelAsync();
}
While the TestWebService() is running I get the LED off(LedOn(LED.WS);). When the TestWebService()has finished the LED comes on.
The BlinkWorker still does not work if started and cancelled inside the Click event.
FYI: If I make a button that starts the blinking and another button that stops it, it works perfectly.
The problem is, you're tying up the UI thread inside that Thread.Sleep. The UI thread is special - it's the only one that can make changes to the UI - so whilst it's busy sleeping, it's not able to service any attempts from your BackgroundWorker or LED_Blink timer callback to change the UI state.
So, you need to not tie up the UI thread. You need to put the Thread.Sleep code (or it's actual real equivalent) into the BackgroundWorkers DoWork handler, or use other means to avoid blocking the UI thread.
Common approaches today would be to make use of async/await if the real work you're trying to do already offers an asynchronous alternative (e.g. await Task.Delay(2000); would be the equivalent of your current Thread.Sleep(2000);). Unfortunately, using async and await would require you to move to a later version of .NET/Visual Studio - but you ought to be considering that anyway. 2010 is quite dated (and also, IMO, probably the worst one to stop on - it was notoriously slow), and .NET 4.0 (as opposed to .NET 4.5.2 or later) is no longer supported.
I would propose that you take a look at the BackgroundWorker class and the ReportProgress method.
I've been trying to perform the simple task written in the title. I could only think of using timer, thread sleep or background worker, but I'm going to do this task only once.. so I would like to avoid making a lot of functions or such just for one time. I tried thread sleep but it doesn't show the mainform before the sleep... Any suggestions please?
The easiest option is to use await Task.Delay:
private async void Form_Load(object sender, EventArgs e)
{
await Task.Delay(timespan);
label1.Text = "Hello world";
}
If you don't have access to await using the version of .NET that you're using, then your best bet would be to use a Timer. Yes it's a fair bit of code. That's simply reflecting the complexity of asynchronous operations. await does a lot to make this simpler; without it, it's just not a problem that lends itself to terse solutions.
Use a System.Threading.Timer in the Form.Load event:
private const int DelayMilliseconds = 500;
private void Form1_Load(object sender, EventArgs e)
{
new System.Threading.Timer(_ => Invoke(new Action(() => _myLabel.Text = "bla")),
null,
DelayMilliseconds,
Timeout.Infinite);
}
Since you only specify a delay and no period, the timer will run exactly once. However, since the timer callback is executed on a different thread, you need to Invoke the action that modifies the label on the UI thread.
Use a System.Timer instance
make an eventhandler with Timer.Elapsed
set timer interval
start timer as application fires up
-after the timer elapses set your label
-stop timer
I'm really struggling with this. I'm creating a winforms application in visual studio and need a background timer that ticks once every half hour - the purpose of this is to pull down updates from a server.
I have tried a couple of different approaches but they have failed, either due to poor tutorial/examples, or to my own shortcomings in C#. I think it would be a waste of time to show you what I have tried so far as it seems what I tried was pretty far off the mark.
Does anyone know of a clear and simple way of implementing an asynchronous background timer that is easily understandable by a C# newbie?
// Create a 30 min timer
timer = new System.Timers.Timer(1800000);
// Hook up the Elapsed event for the timer.
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
...
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// do stuff
}
with the usual caveats of: timer won't be hugely accurate and might need to GC.KeepAlive(timer)
See also: Why does a System.Timers.Timer survive GC but not System.Threading.Timer?
Declare member variable in your form:
System.Timers.Timer theTimer;
On form load (or whatever other time you need to start update polling), do:
theTimer = new System.Timers.Timer(1800000);
theTimer.Elapsed += PollUpdates;
theTimer.Start();
Declare your PollUpdates member function like this:
private void PollUpdates(object sender, EventArgs e)
{
}
I think you need to know about all timer classes. See Jon's answer below.
What kind of timer are you using?
System.Windows.Forms.Timer will execute in the UI thread
System.Timers.Timer executes in a thread-pool thread unless you
specify a SynchronizingObject
System.Threading.Timer executes its callback in a thread-pool thread
In all cases, the timer itself will be asynchronous - it won't "take up" a thread until it fires.
Source: Do .NET Timers Run Asynchronously?
I have a timer named SendTimer, the interval is 30 secs.
protected void SendTimer_Tick(object sender, eventArgs e)
{
SendTimer.Enabled = false;
TransferMoney();
System.Threading.Thread.Sleep(15000);
GenerateTransactions();
SendTimer.Enabled = true;
}
I expected tick event to be called correctly by one thread at the same time. NOT by 2 threads simultaneously. but as I saw in my LOGS it seems to be called by a thread while another thread was in action. Any Idea? Because I disable and enable it respectively.
Windows Forms Timer is a single-threaded by definition. It has nothing about multithreading, because it elapses via WM_TIMER message, being sent to current GUI thread message queue.
So, this:
NOT by 2 threads simultaneously
is incorrect, because even if you have several threads, WinForms Timer has nothing to do with this.