I have used three timers in my program. All are working fine except the third one. i don't know why?
Private Sub Timer3_Tick(sender As Object, e As EventArgs) Handles Timer3.Tick
MessageBox.Show("dont repeat please")
Timer3.Stop()
End Sub
In the form_load i had started the timer, but its showing message box again and again at the interval of 3000ms which i have set. Please help.
Unless there is more to it a quick solution is to just move the call stop the timer to before the message box.
Private Sub Timer3_Tick(sender As Object, e As EventArgs) Handles Timer3.Tick
Timer3.Stop()
MessageBox.Show("dont repeat please")
End Sub
Basically the processing of the code in the Timer3_Ticket sub is being blocked by the display of the message box. The timer running on another thread will continue to raise tick events at each time interval until a message box is closed and the stop method is called.
Related
I have to create a Loading form, while processing a calculus. This form should prevent any action to the other forms while performing this calculus so the most proper command to use should be ShowDialog(). I've also found that I need to run this command, in order to prevent the form freezing, with a BackgroundWorker. So what I've done is to define the button - that will start the calculus - and the BackgroundWorker itself. So this is what I wrote:
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Form18.ProgressBar1.Minimum = 0
Form18.ProgressBar1.Value = 0
Form18.ShowDialog()
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
[calculus code and progressbar progression]
If Form18.ProgressBar1.Value = Form18.ProgressBar1.Maximum Then
Form18.Close()
hrrnativexcel.Visible = True
End If
End Sub
Even if I'm using the BackgroundWorker, when I press the button, the loading form - declared in my code as Form18 - becomes blocked and progressbar gets stuck at 0% loading. Could anyone tell me where I am doing wrong? I've tried to find something about BackgroundWorker with ShowDialog command but I haven't found anything that could help me. Thanks in advance.
How do I stop a timer in its own timer tick? This is the code so far:
Private Sub replyTimer_Tick(sender As Object, e As EventArgs) Handles replyTimer.Tick
MsgBox("Hello!")
Me.replyTimer.Stop()
End Sub
But for some reason, it doesn't stop.
First of all:
The enabled property for the timer must be "False", so the timer doesn't start when form loaded.
and you have to make sure that: in the other parts of your code there is no command or loop to restart the timer.
and to stop the timer... you just need this code :
Private Sub replyTimer_Tick(sender As Object, e As EventArgs) Handles replyTimer.Tick
replyTimer.Stop()
MsgBox("Hello!")
End Sub
so every time the timer starts : the message will pop, and the timer will not restart.
To start the timer again write:
replytimer.start()
i hope my answer was useful to you :)
I have a vb.net winform and I want to know how to add sort of like a session time out to it. For example, I have a varialbe set to 10 min, within that 10 min, if there is no activity (no mouse/no keyboard interaction), I would like to log the user out. Can anyone shine some light on this subject on how to make this work?
First question, why do you want to do in a winform. Such things we generally use in web forms. But even you want to use such things in WinForms you need to use Timer Class.
Whenever you encounter activity, you can just reset the timer by calling Stop then immediately calling Start. Place whatever code you'd like in the Timer's Tick event (assuming this is a System.Windows.Forms.Timer) and you'll be all set.
I'd suggest you use the event Application.Idle.
No need to P/Invoke.
Public Class Form1
Private WithEvents _timer As Timer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' 10 seconds for testing
Me._timer = New Timer With {.Interval = 10000, .Enabled = True}
AddHandler Application.Idle, AddressOf Me.Application_Idle
End Sub
Private Sub Application_Idle(sender As Object, e As EventArgs)
Me._timer.Stop()
Me._timer.Start()
End Sub
Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles _timer.Tick
Me._timer.Stop()
RemoveHandler Application.Idle, AddressOf Me.Application_Idle
' Do something to log the user out
Me.Close()
End Sub
End Class
If you are looking for a way to detect input outside your application Amit's suggestion will not work.
See Detecting idle users in Winforms if that is the case. Calling GetLastInputInfo() and checking the last input value should give you something to go off.
If you are not worried about the user leaving your application, and getting logged out after not using it, use Amit's way of resetting a timer on the input event.
Can i set time limit for a task or a code? for example if i want to show message boxes for 10 seconds and then stop or change the the message body ?
Yes, check out timers. There are three different kinds of timers:
System.Timers.Timer
System.Threading.Timer
System.Windows.Forms.Timer
Which one will work best for you will depend entirely on your specific situation. Given the limited information you provided, I suspect that the easiest way to do what you need to do is to create your own message-box-like form and place a System.Windows.Forms.Timer component on the form (you can find it in the form designer's tool box). Have the form start the timer in its own Shown event. And then show the form using the ShowDialog method.
You can start a Thread and abort it when you want:
Dim t1 As New Threading.Thread(AddressOf MyMethod)
t1.Start()
Timer1.Start()
Private Sub MyMethod()
' Do what you want
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Timer1.Enabled = False
t1.Abort()
End Sub
Hans Passant gave me a great answer here, so I thought of asking for more details to try to understand the way Application.Run() works.
As far as I understand from the docs, it seems that Application.Run() starts a message loop on the current thread, which in turns enables it to process user input (Is that right?). The overloaded version Application.Run(Form) basically does the same, only it exists when the form closes, and it shows the form by default.
That raises a few questions:
How would one do to simply call from the Main() sub a function that can communicate with the user to (message boxes and so on) and wait for it to exit?
When the message loop is started without a form, how do you launch a new form from this loop, and wait for it to exit? ShowDialog could work, unless you don't want the form to display immediately when launched (eg. if you have a for that's launched minimized to the system tray)
Basically, the situation would be as follows: sub `Main` has a list of tasks to execute in 20mn, with a system tray icon telling the user that the program will operate in 20mn. A timer ticks after 20mns, and has to execute say approx. 15 tasks one by one, every time creating an instance of a progress dialog, initially hidden in the taskbar.
`ShowDialog` would display the form, which is not wanted; so the way I would do it would be to pass the progress dialog a callback to a function that starts the next task. But that wouldn't exit the first progress form before the second has exited, would it? Which means 15 forms would end up being opened...
So the solution may be to invoke (begininvoke?) the callback on the main application loop... Only, I don't know how to do this, because I don't have a form associated with the loop to invoke the callback on...
I hope my questions are clear (I might confuse many things, sorry),
Thanks,
CFP.
Drop a Timer, ProgressBar and a BackgroundWorker on the form. First thing you'll want to do is to prevent the form from getting visible when the program is started. Paste this code into the form class:
Protected Overrides Sub SetVisibleCore(ByVal value As Boolean)
If Not Me.IsHandleCreated Then
value = False
Me.CreateHandle
End If
MyBase.SetVisibleCore(value)
End Sub
Use the timer to get the job started. Set its Interval and Enabled properties, add the Tick event handler:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Show()
ProgressBar1.Visible = True
Me.Enabled = False
BackgroundWorker1.RunWorkerAsync()
End Sub
That makes the form visible when the job is started and starts the background worker. Set the BGW's WorkerReportsProgress property to True and add the 3 event handlers:
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'' Do stuff here, call BackgroundWorker1.ReportProgress to update the PB
End Sub
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
ProgressBar1.Value = e.ProgressPercentage
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
ProgressBar1.Visible = False
Me.Enabled = True
Me.Hide()
End Sub
It is up to you to fill in the code for the DoWork event handler. Have it do those 15 jobs, be sure to call BackgroundWorker1.ReportProgess so that the progress bar gets updated. Which is what the ProgressChanged event handler does. The RunWorkerCompleted event handler hides the form again.
You can call the Show() method in the context menu item event for the NotifyIcon so that the user can make your form visible again. Call Application.Exit() in the context menu item that allow the user to quit your app. Make sure you disable that when the BGW is running. Or implement a way to cleanly stop the job.