-
Jun 29th, 2017, 05:17 AM
#1
Thread Starter
New Member
A wait moment like Thread.Sleep(1000) which doesnt freeze the UI nor kills the CPU?
Helloo People,
Sadly no answer yet on my previous question (http://www.vbforums.com/showthread.p...-counting-code), but i managed to think of another way to create a path to succes!
but im still stuck on the pause moment, ive tried alot and the closest way of working how i want it is with an:
- System.Threading.Thread.Sleep(1000)
Pause, but this does totally freeze up my Application.... atleast till the PrivateSub has ended with its lines(sometimes it even crashes), and it kills also the CPU which isnt needed with that kind of small program i am creating^^!
is there anyway i could "pause" between my commands without freezeup the UI? i need the Application to work in the meantime it is sending the keys to a specific process, so a moment of waiting aint a option sadly. ive coded everything else allready, so i'll only need help with this part or: http://www.vbforums.com/showthread.p...-counting-code
as Example what i want to create :
SendKeys.Send("1")
SendKeys.Send("{enter}")
System.Threading.Thread.Sleep(1000)
SendKeys.Send("2")
SendKeys.Send("{enter}")
System.Threading.Thread.Sleep(1000)
SendKeys.Send("3")
SendKeys.Send("{enter}")
System.Threading.Thread.Sleep(1000)
I discovered already that it freezes because of the Wait time.. 1 sec = 1000 is just to much for the system, it works fine with just a few milisec between, but that isnt an option sadly.
Ive tried to understand the "BackgroundWorker Component" ( https://msdn.microsoft.com/en-us/lib...undworker.aspx ) but sadly i do not understand how it works...
i'll hope someone can help me out here with my code, or atleast give it a try to teach me about "BackgroundWorker Component".
Thanks so much peepz, this Forum helped me out allready alot by reading posts!
Greetz B
-
Jun 29th, 2017, 05:43 AM
#2
Re: A wait moment like Thread.Sleep(1000) which doesnt freeze the UI nor kills the CP
welcome to the Forum.
Originally Posted by XtremeNL
Sadly no answer yet on my previous question
i cannot spot any question in this post, maybe thats the reason why?
in regards to your Problem: the easiest way for you (although not the best) would be to add a Sub that does multiple small sleeps like 100ms and a doevents in between until the desired wait time is over. although this is usually not recommendable i still recommend it in your case as it is the most easiest for a beginner. you will have to make sure that your timer is disabled and all controls on your form are disabled while in the Sub or even the timer Sub to avoid any side effects due to the doevents.
as a beginner you should stay away from backgroundworkers and threading as it is way more complicated than what the documentation suggests.
-
Jun 29th, 2017, 06:36 AM
#3
Re: A wait moment like Thread.Sleep(1000) which doesnt freeze the UI nor kills the CP
Originally Posted by digitalShaman
as a beginner you should stay away from backgroundworkers and threading as it is way more complicated than what the documentation suggests.
I would disagree with that. The best way to do this on the UI thread would be with a Timer with an Interval of 1000. You'd put everything to be sent in a list or queue and then start the Timer, sending one item on each Tick event. Using a BackgroundWorker in this case would be easier, because it would just be one method call and one event handler and the existing code would just work as is. It's only really when you need to update the UI that using a BackgroundWorker becomes more complex and, even then, not much.
-
Jun 29th, 2017, 08:40 AM
#4
Re: A wait moment like Thread.Sleep(1000) which doesnt freeze the UI nor kills the CP
thread synchonization is often not taught or mentioned in examples and People build applications that seem to run well at first glance but then fail for unknown reasons from time to time. i therefore do not recommend threading to beginners.
-
Jun 29th, 2017, 08:52 AM
#5
Re: A wait moment like Thread.Sleep(1000) which doesnt freeze the UI nor kills the CP
I don't see any point in a backgroundWorker for this. Sure, it would work, because you could do the sleeps, but so what?
The problem isn't code, it's perception. You want the steps to be in order in a single method, but that has the problem that you have seen. The easiest way to solve the problem is with a timer. You already know about timers, since you use one in the other thread, but you need to think about it in a different way. Every time it ticks, send one set (a key and an enter, it looks like). For this to work, you have to have a means to remember which key should be sent on each tick, but that just means having a variable at form scope (or a static local variable) that keeps track of which step you are in. This can be just an integer that you increment each tick.
In general, though, it is best if you only have a single timer. You can do this, too, though it probably isn't a good idea since you are setting the interval for the timer you already have based on user input.
My usual boring signature: Nothing
-
Jun 29th, 2017, 11:40 AM
#6
Re: A wait moment like Thread.Sleep(1000) which doesnt freeze the UI nor kills the CP
You have a lot of choices, but all of them require making some cognizant design decisions.
No matter how you choose to do it, you need an infrastructure to establish a way to say, 'Do this thing on another thread, and let me know when you finish so I can do something else.'
You can choose a Timer, a BackgroundWorker, a Thread, a Task, and even use new features like Async/Await to do this. But you have to be able to understand how to say, "I want to be able to represent code as a variable so I can schedule it to happen at a later time", or else you'll end up with a difficult-to-maintain mess of state variables and If statements.
So what you've got is a series of things you want to do, mostly just sending keys. Then you want to pause a little to let the other program catch up, and send some more. You start with something serial like this:
Code:
Send("1")
Send("{enter}")
Wait 1s
Send("2")
Send("{enter}")
Wait 1s
What you really want is something that can execute a series of tasks one at a time. If we could make a list of "tasks", that's one way to do so. A Queue is even better for that. So if we made a timer-based solution, we want a skeleton like this:
Code:
Sub WhenTimerTicks:
Stop the timer.
If the queue is not empty:
Remove the first task from the queue.
Execute the task.
End If
Restart the timer.
End Sub
We can do that in code.
One way to represent "tasks" is delegates. That used to require a lot of code, but now there's pretty convenient syntax for it. The delegate you care about here is Action. That is a type. A variable of type Action represents a Sub that takes no parameters. You can execute it just like a normal sub:
Code:
Public Sub Main()
Dim foo As New Action(AddressOf DoSomething)
foo()
End Sub
Public Sub DoSomething()
Console.WriteLine("Hello world!")
End Sub
There's a shorter syntax you can use for on-the-fly delegates. To do so, you make a Sub that doesn't have a name. We call these "anonymous" methods or "lambdas" due to some mathematical papers on the topic of functions. With lambdas, we can shorten the code above:
Code:
Public Sub Main()
Dim foo As New Action(Sub() Console.WriteLine("Hello World!"))
foo()
End Sub
Now we're cooking. Why do we care? Well, if you can put Subs in variables, and call them, we can make a data structure with more than one Sub in it and use that to execute sequentially:
Code:
Public Sub Main()
Dim tasks As New Queue(Of Action)()
tasks.Add(Sub() Console.WriteLine("Hello World!"))
tasks.Add(Sub() Console.WriteLine("Hello Again!"))
While Not tasks.Count = 0
Dim task As Action = tasks.Dequeue()
task()
End While
End Sub
That should look familiar.
So let's say you have a timer set for 1000ms. At Form startup (the Shown event, probably), you could have:
Code:
Private _tasks As New Queue(Of Action)()
Private Sub OnShown(...)
_tasks.Add(Sub() SendKeys.Send("1{enter}"))
_tasks.Add(Sub() SendKeys.Send("2{enter}"))
...
End Sub
If you've got a 1s timer set up, its handler could look like:
Code:
Private Sub When_timer_ticks(...) Handles Timer1.Tick
Timer1.Stop()
If _queue.Count > 0
Dim nextTask As Action = _tasks.Dequeue()
nextTask()
End If
Timer1.Start()
End Sub
That is just one way, but even if you pick a way that doesn't use a timer, you'll be writing code very much like that. This is the fundamental pattern for executing a series of tasks in sequence.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Jun 30th, 2017, 12:53 AM
#7
Re: A wait moment like Thread.Sleep(1000) which doesnt freeze the UI nor kills the CP
so you now got recommendations and explanations on how it could be done the "correct" way and i do agree on These. but i still believe that as a beginner it is important to have quick success to fuel Motivation even if the solution is not perfect or correct. take your time and study what was suggested and if you hit a wall you can still come back and ask questions or Chose the easy route. i guess you will learn something either way.
but please, before you start of with multithreading, read on the requirements and pitfalls of synchronized Access to shared resources.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|