I have been trying in various ways to make my program sleep for 10 seconds before running the next line of code.
this.SetContentView (Resource_Layout.Main)
let timer = new System.Timers.Timer(10000.0)
async{do timer.Start()}
this.SetContentView (Resource_Layout.next)
I can't get any solution to work.
If you want to use async rather than the more direct way (of creating a timer and setting the content view in the event handler of the timer), then you need something like this:
this.SetContentView (Resource_Layout.Main)
async{
do! Async.Sleep(10000.0)
this.SetContentView (Resource_Layout.next) }
|> Async.StartImmediate
The key points:
Using do! Async.Sleep you can block the execution of asynchronous computation
By moving the SetContentView call inside the async, it will happen after the sleep
Using Async.StartImmediate, you start the workflow - and the sleeping ensures that the rest of the computation runs in the same threading context (meaning that it will run on the UI thread and the code will be able to access UI elements).
Related
I'm trying to build an NES emulator using winit, which entails building a game loop which should run exactly 60 times per second.
At first, I used std::thread to create a separate thread where the game loop would run and wait 16 milliseconds before running again. This worked quite well, until I tried to compile the program again targeting WebAssembly. I then found out that both winit::window::Window and winit::event_loop::EventLoopProxy are not Send when targeting Wasm, and that std::thread::spawn panics in Wasm.
After some struggle, I decided to try to do the same thing using task::spawn_local from one of the main asynchronous runtimes. Ultimately, I went with async_std.
I'm not used to asynchronous programming, so I'm not even sure if what I'm trying to do could work.
My idea is to do something like this:
use winit::{window::WindowBuilder, event_loop::EventLoop};
use std::time::Duration;
fn main() {
let event_loop = EventLoop::new();
let _window = WindowBuilder::new()
.build(&event_loop);
async_std::task::spawn_local(async {
// game loop goes here
loop {
// [update game state]
// [update frame buffer]
// [send render event with EventLoopProxy]
async_std::task::sleep(Duration::from_millis(16)).await;
// ^ note: I'll be using a different sleep function with Wasm
}
});
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
// ...
_ => ()
}
});
}
The problem with this approach is that the game loop will never run. If I'm not mistaken, some asynchronous code in the main thread would need to be blocked (by calling .await) for the runtime to poll other Futures, such as the one spawned by the spawn_local function. I can't do this easily, since event_loop.run is not asynchronous.
Having time to await other events shouldn't be a problem, since the control flow is set to wait.
Testing this on native code, nothing inside the game loop ever runs. Testing this on Wasm code (with wasm_timer::Delay as the sleep function), the game loop does run, but at a very low framerate and with long intervals of halting.
Having explained my situation, I would like to ask: is it possible to do what I'm trying to do, and if it is, how would I approach it? I will also accept answers telling me how I could try to do this differently, such as by using web workers.
Thanks in advance!
The first question is when the event loop starts ?
I read in a site that it's start after the main method
but why when we try something like this
main()async {
Future(()=>print('future1'));
await Future(()=>print('future2'));
print('end of main');
}
//the output is :
//future1
//future2
//end of main
in this example the event loop start when we use the await keyword and
after the event loop reaches the future2 it's paused ?
or i am wrong :(
The second question is how the events is added to event queue
if it's FIFO why in this example the future 2 is completed before
future 1
main(){
Future.delayed(Duration(seconds:5) , ()=>print('future1'));
Future.delayed(Duration(seconds:2) , ()=>print('future2'));
}
The event loop run when there is nothing else running (e.g. main method is done, you are waiting for some future to complete).
Your example makes sense because the first line puts an event on event queue so now the first item in the queue is "print('future1')". In the next line, you are putting another event on the queue which calls "print('future2')" and now you await for this event to be done.
Since your main method is not waiting for something then the event loop is going to be executed. Since the first event on the queue was "print('future1')" then this is going to be executed first. But since the main method is still waiting for the future "print('future2')" to be complete then the event loop takes another event to be executed which are going to be "print('future2')".
Since this event was the one the main method was waiting for (and there is no more event on the event queue) then main() are going to run the last call "print('end of main')".
In your next example, you think that Future and Future.delayed are the same which it is not. With Future.delayed there are not going any event in the event queue before. Instead, there are running a thread outside the VM which knows when the next timer should trigger which ends up putting an event on the queue. So the event is only being put on the event queue when the timer has been expired (and therefore, the future2 are going to be executed first).
using QtCreator to make a loftier interface to a sofware.
There is basically a set of buttons to tune and inputs, a start and stop job
buttons, my problem comes from an infinite loop that freezes the display so I came up with using fork() so that the loop have to compete with the main program instead of eating up the whole resources (no multithreading), but the program crashes spiting:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not
been called
[xcb] Aborting, sorry about that.
a.out: ../../src/xcb_io.c:274: poll_for_event: Assertion
`!xcb_xlib_threads_sequence_lost' failed.
the fonction calling the loop is called 'ON', 'OFF' is supposed to exit the forked process.
//in button 'ON' func
ps = fork();
if(getpid() == ps)
{
while(1)
{
strcpy(word, charset(minlength, maxlength, N));
ui->pass->setText(word);//operation on the display
....SNIP
}
}
//In button 'OFF' func
if(getpid() == ps)
exit(0);
I'm really asking what is the correct way of starting a while(1) and be able to break, exit, or return from it while not freezing the window using QT, thanks.
You crash probably here:
ui->pass->setText(word);//operation on the display
as in Qt, you can not change UI from non UI threads directly. Only from signals and slots mechanism.
The proper way to not freeze UI is obviously to compute lengthy operations in another thread.
You can achieve this in several ways:
One is by sub-classing QObject class to create 'worker object' which would perform all heavy operations. You create new QThread object that should live as long as you need your object. And use QObject::moveToThread method to move created object to new thread. To control your worker object you should send signals from object and call it's slots also via signal-slot mechanism. If you call them directly - they will be executed in caller thread (so do not perform stuff like worker->startHeavyJob(); in UI thread). Instead emit signal in UI (emit sigStartHeavyStuff();) and connect it to slot of your worker object (slotDoHeavyStuff();)
if you do not want to bother with this (if operation is pretty small)
- you can use QApplication::processEvents() to process events in UI event loop while going in your infinite while loop.
Another way is to use QtConcurrentRun framework to run function in separate thread which manages itself. Threads are taken from thread pool and are managed by Qt. This approach looks like something you want to do. Though you still will be able to access UI objects only through signals and slots.
I see one big issue in the presented code that is causing your freeze: You never let Qt process anything while you are in the loop. You need to allow Qt to run it's event loop. The easiest way is to use QApplication::processEvents() inside the loop.
I'm also not a fan of a while(1) loop for a couple of reasons. The first of which is that it can eat machine cycles waiting for things to happen. I doubt you really need to run the code as fast as possible, you could probably get away with some sleeping in your loop.
The other issue is that it is hard to break out. A cleaner approach would be something like this
void MyClass::on_pushButton_ON_clicked()
{
MyClass::done = false; // this is a class attribute
while (!MyClass::done) {
QApplication::processEvents();
//...
}
}
void MyClass::on_pushButton_OFF_clicked()
{
MyClass::done = true;
}
I have a class with the delegates for a URLSession. I intend to use it with a background configuration. I understand that the handlers are called when a certain event happens, such as didFinishDownloadingTo.
However, I do have the handle function on my ExtensionDelegate class:
func handle( _ handleBackgroundTasks:
Set<WKRefreshBackgroundTask>)
// Sent when the system needs to launch the application in the background
to process tasks. Tasks arrive in a set, so loop through and process each one.
for task in handleBackgroundTasks {
switch task {
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
I wonder: where should I handle the data I receive after a download? At the didFinishDownloadingTo or at that function on my ExtensionDelegate class, on the appropriate case of the switch statement?
Another question on the same cycle: I read everywhere that one must remember to setTaskCompleted() after going through the background tasks. But I read elsewhere that one should not set a task as completed if the scheduled data transfer hasn't finished. How do I check that?
There is a very good explanation here.enter link description here
It worked when I had an array with my WKURLSessionRefreshBackgroundTask. Then, at the end of my didFinishDownloadingTo, I get the task on that array that has the same sessionIdentifier as the current session.configuration.identifier, and set it as complete.
Is there any way to halt execution in ActionScript, such as a sleep() method?
I know that there is a setTimeout() method, but setTimeout() just sets up an event for deferred execution.
No. There is no sleep. Sorry.
See my answer here for options: ActionScript: pushing a closure onto the event stack?. It doesn't talk about sleeping, but I tried to provide an overview of deferred function calling.
You need to think in terms of not sleeping. Actionscript is not that kind of language. Because the flash player alternates between frame renders and code execution, sleeping in the code is always a bad idea, which is why there is no method to do it.
Having said that, you could achieve this by using the blocking method ExternalInterface.call, and in Javascript executing a blocking method (like XHR request).
Absolutely idiotic though, so don't do it.
Perhaps what you need is a Timer.
There's no way to pause all execution of an application as in PHP, but there are workarounds (unless you set a breakpoint or create a runtime error on purpose, don't think that's what you meant). Probably this is because usually flash applications are meant to execute all the scripts in less than one "frame".
It's common to be able to "pause" the animations of a website when the user unfocus it. This can be made by listening to Event.DEACTIVATE and then remove the ENTER_FRAME listeners and kill all ongoing processes.
You could also create a central EventDispatcher to replace the internal ENTER_FRAME, this way you seamlessly control speed of execution as well as pausing / resuming (won't stop executing scripts, nor asynchronous handlers such as loaders etc. though).
Yes, there is, though be aware of the 15 second script timeout. ( You can change that 15 second script timeout in the Publish Settings... )
I've found in the past that if you're looking for this functionality, you're doing something wrong :)
Whatever you're trying to accomplish is probably calling for an Event listener instead.
//adding this ENTER_FRAME event listener just to show that the script pauses for one
// second before the first frame executes
addEventListener( Event.ENTER_FRAME, onFrame );
function onFrame( event:Event ):void {
trace( "first frame occurs after pause of", getTimer() + " ms" );
removeEventListener( Event.ENTER_FRAME, onFrame );
};
var startTime:int = getTimer();
var pauseTime:int = 1000;
while( ( getTimer() - startTime ) < pauseTime ) {
//do nothing... we're effectively pausing here...
}