I am writing an audio recording application for WP7. I have a DispatcherTimer object in my ViewModel class, that when the recording is happening, counts the elapsed seconds to show the length of the recording to a user. I have the following problem with the app:
The tick interval for the DispatcherTimer is set to one second (1000) ms.
When I press the start button, the DispatcherTimer starts.
When I press the stop button, the DispatcherTimers thread exits. (in a second!, thought I didn't intend it to be that way))
If I do press the start button after pressing stop to swiftly (less then a second inbetween), my DispatcherTimer fails to start again, since it hasn't yet stopped. (it's thread hasn't exited)
Basically, my biggest concern is why does DispatcherTimer has to wait until it's time for its tick, to realize that it has been stopped, and the thread it created to perform ticks in has to exit?
How can I work around this problem? Thank you.
DispatcherTimers are not guaranteed to execute exactly when the time interval occurs, but they are guaranteed to not execute before the time interval occurs. This is because DispatcherTimer operations are placed on the DispatcherTimer queue like other operations. When the DispatcherTimer operation executes is dependent on the other jobs in the queue and their priorities.
Reference: http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer(v=VS.95).aspx
You should better use a System.Threading.Timer, which is a timer class that fires on a separate thread. This is good for purely numerical timing, where you're not trying to update the UI, etc.
Related
I'm making a scheduler with simple Unix style educational OS. I have the problem: How to generally block timer interrupt, when it overlaps with process end or sleep?
In the moment of overlapping, timer handler called before the process move on to sleep or end state.
Wanted operation
-timer interval is 10 ticks for example.
Run for 100 ticks
Process terminate
Timer handler calls schedule
Current operation
Run for 100 ticks
Timer handler calls schedule
Scheduled to another process.
Moments later
Rescheduled to initial process.
Process terminate
Can anyone suggest a general idea to solve this?
It was UP.
Well, maybe this was stupid question.
I just solved it by doing scheduling 1 tick later, kinda hacky way.
Hope there's more correct answer.
the state machine's first state is waiting for one event, if the event doesn't happen in certain days, the status machine will switch to the second state. If the event happened in the period, the state machine will switch to the third state.
I have two option:
1, Use a timer. Set up a timer as certain days. When time is up, checking does the event happened or not. If happened, switch to the third state. If not, switch to the second state. It is possible that thousands of timers will be created in the period.
2, Use a looping with routine. Start a routine to run a loop. Every half hour, the goroutine will check the event happened or not. If the event happened, switch to the third state. Else, keep looping until expired the certain days, then switch to the second state.
My question is time.Timer vs goroutine, which is more suit for this case?
Since you mention a time period of days, of the two given, you should probably go with the second option. This way you can store state to a file (or database) and restart the process if necessary. The first option makes storing the state more difficult, but still possible.
When i press button1 (execute) on UI i run AsyncTask. The task was run success.
I press another button2 (cancel) to stop asynctask from main thread
asynctask.cancel(true);
but AsyncTask thread dont self kill! (see second screenshot)
The asynctask switch to WAIT mode
then i can press button1 (execute) again and run NEW task and press button2 (cancel)
And i have queations:
Why task dont selfkill after used cancel(true)?
And whay mean WAIT mode?
AsyncTask under the hood uses a ThreadPoolExecutor. Those threads might not go away for a bit because it'd be a waste to keep creating and tearing down those threads too often. After a while if you create more AsyncTasks you'll find that it'll stop creating new threads and it'll re-use the old ones.
Update to address some details:
You would think that if there are free threads in the pool, it wouldn't create new ones, but this isn't exactly true. The idea is that there's a certain number of threads that are useful to have around to keep processing asynchronous tasks. This is called the core pool size. In Android's AsyncTask case, they seem to have set it to 5. If you look at the documentation for ThreadPoolExecutor it says:
When a new task is submitted in method execute(Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle.
There's also a maximum fittingly called the maximum pool size.
Currently, I call DoEvents in order to check if Button Foo in Form Bar has been clicked. This approach works but it takes too much processing power, delaying the program.
I believe that the delay could be reduced if I could only check if Button Foo has been clicked, instead of all the other forms that DoEvents has to go through.
Any ideas on how can I check if Button Foo was clicked?
VB6 was not really designed for what you seem to be doing (some sort of long-running straight-line code that does not exit back to give the message loop control). Normally such a task would be delegated to a worker thread, and in VB6 this means some external component implemented in C++ most of the time.
There are only a very few kinds of approaches to take to do this for your ad-hoc logic:
Hacks creating separate threads via API calls, not very reliable in VB6 for a number of reasons.
A tricky thread-per-object ActiveX EXE implementing a class to handle your long-running workload.
A separate non-interactive worker process to be run and monitored by your GUI program.
That's pretty much it.
The prescribed method of doing this sort of thing is described in the VB6 documentation. You break your long-running loop up and invert the logic into a repeatable "quantum" of work (like n iterations of your processing loop), and maintain the state of your workload in Form-global data. Then you use a Timer control with its interval set to 1 or 16 (hardly matters, they normally take at least 16ms to trigger) and run your workload quantum within its event handler.
So if you simply had a loop that currently iterates 100,000 times doing something you might break it up so that it runs 500 times for each Timer tick. The quantum size will probably need to be tuned based on what is done within the loop - 500 is just a value chosen for illustration. You'll want to adjust this until it leaves the UI responsive without starving your background workload too much (slowing completion down).
If your code is heavy enough to not call DoEvents or just finish running periodically, then your app won't even know the button has been pressed. The DoEvents call allows windows, and your application to catch up on all notifications.
The correct way to resolve this is a worker thread (see this article on how to do something like this in VB6) but failing that, a periodic DoEvents is required and in turn, some re-entrancy blocking on the call into the long running code.
It is best to describe my question in an example:
We create a Windows Event handle by CreateEvent, with manualReset as FALSE.
We create 4 threads. Ensure that they all start running and waiting on the above event by WaitForSingleObject.
In the main thread, in a for loop, we signal this event 4 times, by SetEvent. such as:
for (int i = 0; i < 4; ++i) ::SetEvent(event);
My question is, can we say that all these 4 threads will certainly be waken up from waiting on this event?
According to my understanding of Windows Event, the answer is YES. Because when the event is set, there is always a thread waiting for it.
However, I read on MSDN that "Setting an event that is already set has no effect". Since the waiting threads probably do not get a chance to run while main thread setting event in the loop. Can they still be notified and reset the event to nonsignaled? If the event is not reset, the following SetEvent in the loop is obviously useless.
Or the OS kernel knows which thread should be notified when an event is set, and reset this event immediately if there is a waiting thread. So the waiting thread does not need to be schedule to reset the event to nonsignaled?
Any clarification or references are welcome. Thanks.
Because when the event is set, there is always a thread waiting for it.
No, you don't know that. A thread may indefinitely suspended for some reason just before the NtWaitForSingleObject system call.
Since the waiting threads probably do not get a chance to run while main thread setting event in the loop.
If a thread is waiting for an object, it doesn't run at all - that's the whole point of being able to block on a synchronization object.
Can they still be notified and reset the event to nonsignaled? If the event is not reset, the following SetEvent in the loop is obviously useless.
The thread that sets the event is the one that resets the signal state back to 0, not the thread that gets woken up. Of course, if there's no thread waiting the signal state won't be reset.
Or the OS kernel knows which thread should be notified when an event is set, and reset this event immediately if there is a waiting thread.
Yes, the kernel does know. Every dispatcher object has a wait list, and when a thread waits on an object it pushes a wait block onto that list.
In a word? No.
There's no guarantee that each and every call to Set() will signal a waiting thread. MSDN describes this behavior as follows:
There is no guarantee that every call
to the Set method will release a
thread from an EventWaitHandle whose
reset mode is
EventResetMode::AutoReset. If two
calls are too close together, so that
the second call occurs before a thread
has been released, only one thread is
released. It is as if the second call
did not happen. Also, if Set is called
when there are no threads waiting and
the EventWaitHandle is already
signaled, the call has no effect.
(Source)
If you want to ensure that a specific number of threads will be signaled, you should use a more suitable kind of synchronization primitive, such as a Semaphore.
When you do SetEvent(event), since your manual reset is set as false for the event, any thread (windows doesnt specify any preferences) from one of the four would get passed the waitforsingleobject() and on the subsequent calls the other 3 threads would randomly be selected since your event is autoreset after releasing every thread.
If you're trying to imply the threads are re-entrant, the threads getting released every time would again be one out of four randomly by OSes choice.