Jump to content

Best way to call function at interval


jordRiot

Recommended Posts

Evening,

 

Hopefully a straight forward request! What is the best way to call a function repeatedly using the API?

 

I've tried using threads and tasks (async/await) but they both seem to cause crashes quite quickly. Would one of the LCPDFR ENGINE TIMERS be a better means to poll a function?

 

To provide a bit of context:

private bool isLoading = false;
async Task<string> asyncFunc()
{
     await Task.Delay(2000);
     if (!isLoading)
     {
         isLoading = true
         //AWAIT CODE HERE
         isLoading = false;
     }
            
      Task<string> returnedTaskResult = asyncFunc();
      return aString;
}

public override void Initialize()
{
      // Bind console commands
      this.RegisterConsoleCommands();

      // Listen for on duty event
      Functions.OnOnDutyStateChanged += this.Functions_OnOnDutyStateChanged;

      Log.Info("Started", this);
      Task<string> returnedTaskResult = asyncFunc();
}

What I'm using at the moment-ish

 

Cheers,

 

~Jordan

Link to comment
Share on other sites

Alas the script engine of the game doesn't allow threading in any way. I wish it would.

How about using the tick event with an interval set to 2000 and a validation of the return value?

 

EDIT: Just forget it. I'm no member of the LCPDFR dev team and I guess you don't care for my opinion anyway.

Edited by Cyron43
Link to comment
Share on other sites

  • Management Team

Natives have to be invoked on a scripting thread, so you can't simply call them from another thread. As  you already said, a timer will work just fine. We offer two different versions of timers:

 

A normal timer, working just like System.Windows.Forms.Timer but running within the scripting thread context:

            this.timer = new LCPD_First_Response.Engine.Timers.Timer(
                2000,
                delegate
                {
                    LPlayer.LocalPlayer.Money += 50;
                });

Note that I used an anonymous function instead of a callback function, I prefer it in most cases where you don't have much code for readability.

 

And you could also use a so-called NonAutomaticTimer, it works a little different:

 
// Put this in Initialize
this.timer = new NonAutomaticTimer(2000);
 
// Put this in Process
            if (this.timer.CanExecute())
            {
                LPlayer.LocalPlayer.Money += 50;
            }
 

This way the timer code is not executed automatically, but only when reached within your Process logic and if the time has elapsed.

 

If you really want to call natives from another thread, you can use DelayedCaller.Call to launch them from a thread, they will always run on the main scripting thread. But they will be added to a queue and Call will return immediately. If you also need to access a return value in the thread and want to wait for it before processing further in thread, use something like this which blocks the thread until the code was invoked on the main scripting thread:

// Code below will execute on main scripting thread and thread will be blocked until it has been invoked
System.Func<bool> isSpeechPlayingLogic = () => LPlayer.LocalPlayer.Ped.IsAmbientSpeechPlaying;
if (!DelayedCaller.InvokeOnMainThread(delegate { return isSpeechPlayingLogic(); }, 1))
{

}

Please do not PM me unless really necessary (knowing you helps). If you think you need my attention in a topic, tag me.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...