I am making a EA for backTest.
Normally program works like this.
Ontick() is called until the end of certain period.
OnDeinit() OnTester() are called.
However now I want to stop in OnTick() and goto 2).
like this,
void OnTick()
{
if (cnt > 100) {OnTick();OnTester();//Finish program here}
}
I think I could stop in OnInit() (to check user's initial setup etc...)
However can I stop EA in OnTick()???
In summary, what I want to do is,
Call OnTester() from inside of the OnTick() and finish the program.
Yes, this is also possible:
syntax is:
void ExpertRemove();
The Expert Advisor is not stopped immediately as you call ExpertRemove(); just a flag to stop the EA operation is set. That is, any next event won't be processed, OnDeinit() will be called and the Expert Advisor will be unloaded and removed from the chart.
So the OnDeinit(){...}-handler is activated "automatically", once a first call to the ExpertRemove() system function has raised the pre-termination flag.
If your logic requires, put this call into a "manually" called OnTester() handler, relying on it being invoked as posted aboveif( cnt > 100 ) { OnTester(); // having the "killer"-ExpertRemove() there ... }
and you are done.
You might have noticed, there should not be the posted OnTick()-call inside the if(){...}-code-block, as it would never let the code-execution reach the manually-pre-scribed call to the OnTester(), but will remain in a lethal never ending loop of manually-injected endless diving of re-entries into the OnTick(){...}-handler, having no way to exit from.
Related
import 'dart:io';
main() async {
await loop();
while(true){
print('Your input:${stdin.readLineSync()}');
}
}
loop(){
print('stuck');
//Future.delayed(Duration(days:5),(){});//works fine
//while(true);//does not work
}
Why cannot users input anything when while(true) is being executed inside loop(), instead, Future. delayed works fine with stdin?
Dart is single-threaded. That means that at most one piece of Dart code is running at a time (per isolate if you have isolates).
Code like while(true); is a tight loop that never stops. No other code will run in the same isolate until the loop ends, and the loop never ends. This is busy waiting, and it does not give other code time to run.
You never even get to the part of your code which calls stdin.readLineSync().
The await in front of loop() does nothing, because the code never gets to it. It calls loop and stays there forever.
If you create a Future.delayed(...), then ... it doesn't actually do anything. You are not returning it, so the await won't be waiting for it to complete. All you do is to create a timer, create a Future object, and when the timer runs out, something will happen which will complete the future. If you return the future, then the await will wait for that.
What did you want or expect this code to do?
I'm new to MQL language, so please correct me if I described something wrong.
I made an script by the script editor to place orders automatically. The program should be never stopped unless by manually termination. My code looks like that:
void onStart()
{
While(true)
{
Sleep(10000);
MakeOrder(....);//of course actual code is much more complicated
}
}
The only preset functions I use are trade functions, math functions and time functions.
The code works well for most of the times that can continue running at least for 48 hours, but sometimes it might unexpectedly stopped reporting deinit reason 4(which is the same exit code if I click stop button when debugging) within one hour after starting. It looks that MQL doesn't have try...catch module, and getting error in some coding lines won't stop it. I wonder what might have happened behind the termination? Or how can I ignore it, so at least the program can automatically restart?
You should check the OnTimer and OnTick functions.
And recommended to use IsStopped() in the While loop.
void onStart()
{
while(!IsStopped())
{
Sleep(10000);
MakeOrder(....);//of course actual code is much more complicated
}
}
Uninitialization Reason 4 is : chart has been closed. In MT4, you always need to run a script on a chart (window), so of course if this chart is close for any reason, your script will terminate. There is nothing you can do to prevent that.
As suggested, adding IsStopped() will terminate your loop (and script), so what you can do is to add some code after your loop to notify you the script is being terminated.
For example :
void OnStart()
{
//---
while(!IsStopped())
{
Sleep(10000);
//MakeOrder(....);//of course actual code is much more complicated
}
//---
if(UninitializeReason()==REASON_CHARTCLOSE)
{
string msg="Chart is closed and the script is terminated.";
Alert(msg);
SendNotification(msg);
}
}
When I attach a custom indicator to a chart, close MT4 and reopen it, the indicator initialises normally but every instance of AccountInfo() or SymbolInfo() in the first run of start() returns 0.0, causing several functions to throw a 'zero divide' error. When I reinitialise the indicator (without closing MT4), AccountInfo() and SymbolInfo() return the values they usually do.
If I comment out all functions that are dependent on these two, the indicator initialises without throwing errors after restarting MT4.
Has anybody had a similar issue?
To clarify: the problem only arises when I attach the indicator to the chart, close MT4 and reopen it again; when I attach it when MT4 is already open, AccountInfo() and SymbolInfo() return normal values.
Additional information:
using #property strict
using start() instead of OnCalculate() (so I can run the main function manually without waiting for a new tick)
the requested account or symbol property has no influence on the problem
It happens quite often that some data is not available in MT4 at some moment of time. The best thing you can do is to check whether the result is accepted (>0 if you call time, quotes, other data that cannot be zero) or to check the last error, then Sleep(50) and try again. Most likely 2-5th attempt is successful so you need that in a loop.
It is possible that you need to know at least Account Number that cannot be zero. After you receive succesful result, all other data seems to loaded correctly.
int OnInit()
{
if(!initializeAccountInfo())
return(INIT_FAILED);
// ... other checks that you need
return(INIT_SUCCEEDED);
}
bool initializeAccountInfo()
{
int accountNumber=0, attempt=0, ATTEMPTS=50, SLEEP(50);
while(attempt<ATTEMPTS)
{
accountNumber=AccountInfoInteger(ACCOUNT_LOGIN);
attempt++;
if(accountNumber==0)
Sleep(SLEEP);
else
break;
}
return accountNumber>0;
}
Well I find weird point of message loop.
first, lock this code below
MSG msg = {0};
while( WM_QUIT != msg.message )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
Render(); // Do some rendering
}
}
It is a tutorial of directx and this part is part of message loop.
If I click a mouse, It goes to queue as Message.
So Input like this should be process in proc function of win api.
Now that peekMessage return true, render() will not be called in frame when I clicked.
I think code be changed if~else to if~if for render when I click.
Can you explain this??
Your understanding is close, but not quite right. The loop isn't run once per frame. Rather, what happens is that for every iteration of the loop, either a single message is processed or Render is called. Effectively this makes rendering the lowest priority, but keeps your application responsive. The loop may be run many times or few times for each frame drawn, depending on how much work there is to do.
Does Render directly call Present? Or does it invalidate the window? If it invalidates the window, you would not want to change to always calling Render like you mentioned, because you'd risk not redrawing the window between renders.
Essentially this loop will process any pending Win32 messages for your window, and if there aren't any, it will render a frame. If it sees a WM_QUIT message, it exits the loop to quit the app.
There's no need for a 'throttle' because DirectX Present will block the thread (i.e. suspend it) if there are already 3 frames pending to render.
This model assumes you are doing one frame 'Update' per 'Render' call which isn't that realistic for a game, but it is simple for the tutorial. Extending the tutorial loop with StepTimer would look something like:
#include “StepTimer.h
DX::StepTimer g_timer;
...
MSG msg = {0};
while( WM_QUIT != msg.message )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
g_timer.Tick([&]()
{
Update(g_timer); // Update world/game state
});
Render(); // Do some rendering
}
}
...
void Render();
void Update(DX::StepTimer& timer);
StepTimer defaults to using variable step updates which means Update is called once per frame with whatever time delta and then Render is called once.
You can use a fixed-step update (say 60 times a second) like this:
g_timer.SetFixedTimeStep(true);
g_timer.SetTargetElapsedSeconds(1.f / 60.f);
In this mode, you'll have all pending Win32 messages processed, and then Update is called as any times as needed to keep up an average of 60 fixed-step updates per second, and then Render is called once.
The Render() inside the else basically gives preference to handling messages in the queue over rendering. Moving the mouse over the directx rendered window will add messages quickly to the message queue, but not fast enough to cause rendering to be delayed to any degree you'd ever see it. There is no advantage to rendering with each iteration because the iterations happen much faster than each frame is generated in your swapchain and much faster than a new message could swamp your queue. Most computers today will run this loop more than once per millisecond and even mouseover events happen less often than this. You wouldn't be wrong to render with every iteration, it's just unnecessary. With the example running, moving your mouse over the directx window as quickly as you can will cause fewer than 10% of the iterations of this loop to handle a message and delay rendering.
This message loop is executed as quickly as possible and has no facility to detect when the swapchain is ready to render. The PeekMessage checks to see if there's a message in the queue. If there is, it processes it, if not it Renders. What you're worried about is that a sequence of window events will cause the render to be delayed, but that's practically impossible. No matter how fast messages are sent to the queue, the swapchain is rendered more than 10 times faster than it needs to even for 60fps. This loop is the cause of high CPU utilization. The reason for it may be to simplify the tutorial, but as it's an inherently complicated environment. You might modify the swap chain in a separate thread if you're worried about the message queue delaying frame rendering.
To improve the CPU efficiency of the example program, just add a Sleep(8); at the bottom of the Render() routine. This will cause the message handler/render thread to pause between cycles handling messages and rendering at about 120 times per second. You can improve upon this by using high resolution timers and a modulus based sleep between cycles.
A good source of information to improve this example can be found here.
I have a wxLua Gui app that has a "Run" button. Depending on selected options, Run can take a long time, so I would like to implement a "Cancel" button/feature. But it looks like everything in wxLua is working on one Gui thread, and once you hit Run, pressing Cancel does nothing, the Run always goes to completion.
Cancel basically sets a variable to true, and the running process regularly checks that variable. But the Cancel button press event never happens while Running.
I have never used co-routines; if the Run process regularly yields to a "Cancel check" process, will the Cancel event happen then?
Or is there another way?
(the following assumes that by "Run" you mean a long running operation in the same process and not running an external process using wxExecute or wxProcess.)
"Cancel" event is not triggered because by executing your Run logic you have not given a chance to the UI to handle the click event.
To avoid blocking the UI you need to do something like this. When you click Run button create a co-routine around the function you want to run:
coro = coroutine.create(myLongRunningFunction)
Your Run event is completed at this point. Then in EVT_IDLE event you will be resuming this coroutine as long as it's not complete. It will look something like this:
if coro then -- only if there is a coroutine to work on
local ok, res = coroutine.resume(coro, additional, parameters)
-- your function either yielded or returned
-- you may check ok to see if there was an error
-- res can tell you how far you are in the process
-- coro can return multiple values (just give them as parameters to yield)
if coroutine.status(coro) == 'dead' then -- finished or stopped with error
coro = nil
-- do whatever you need to do knowing the process is completed
end
end
You will probably need to request more IDLE event for as long as your process is not finished as some operating systems will not trigger IDLE events unless there is some other event triggered. Assuming your handler has event parameter, you can do event:RequestMore(true) to ask for more IDLE events (RequestMore).
Your long-running process will need to call coroutine.yield() at the right time (not too short as you will be wasting time to switch back and forth and not too long for users to notice delays in the UI); you probably need to experiment with this, but something timer-based with 100ms or so between calls may work.
You can check for Cancel values either in your IDLE event handler or in the long-running function as you do now. The logic I described will give your application UI a chance to process Cancel event as you expect.
I don't use WXWidgets, but the way I implement cancel buttons in my lua scripts which use IUP is to have a cancel flag, which is set when the button is pressed and the progress display is checked for during the run.
Usage is like this
ProgressDisplay.Start('This is my progress box',100)
for i=1,100 do
ProgressDisplay.SetMessage(i.." %")
fhSleep(50,40) -- Emulate performing the task
ProgressDisplay.Step(1)
if ProgressDisplay.Cancel() then
break
end
end
ProgressDisplay.Reset()
ProgressDisplay.Close()
If you want to see the definition for the ProgressDisplay see:
http://www.fhug.org.uk/wiki/doku.php?id=plugins:code_snippets:progress_bar