Register for your free account! | Forgot your password?

You last visited: Today at 00:34

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Delaying tasks

Discussion on Delaying tasks within the CO2 Private Server forum part of the Conquer Online 2 category.

Reply
 
Old   #1
 
U2_Caparzo's Avatar
 
elite*gold: 0
Join Date: Aug 2011
Posts: 314
Received Thanks: 90
Delaying tasks

Well, sorry for post this here, but programming section is almost only deutsch.
I was tired of study and started programming a bit, and thought that might be a good idea to create this class (i know that something like this exists in project x, don't know exactly how did he code it)
this one is using two AutoResetEvents, one to notify when a new action was added and another one to force it's WaitOne() timeout, so basically the thread will work only when an action must be executed, i think that i'll have to lock the SortedList used to avoid a possible exception.

the question is, will be this better than a thread/timer with a const interval and checking all the actions that must be executed, and if there are others ways to do this.

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace CoreLib.Threading
{
    public class LazyTask
    {
        private static SortedList<DateTime, Action> delayedActions = new SortedList<DateTime, Action>();
        private static Thread thread = new Thread(Loop);
        private static AutoResetEvent synchronizer = new AutoResetEvent(false);
        private static object syncRoot = new object();
        private static bool started = false;

        private static void Loop()
        {
            while (true)
            {
                synchronizer.WaitOne();
                KeyValuePair<DateTime, Action> pair;
                lock (syncRoot)
                    pair = delayedActions.First();
                int millisecondsForNextInvoke = (int)Math.Max((pair.Key - DateTime.Now).Ticks / 10000, 0);
                synchronizer.WaitOne(millisecondsForNextInvoke);
                lock (syncRoot)
                {
                    if (DateTime.Now.Ticks >= pair.Key.Ticks)
                    {
                        pair.Value();
                        delayedActions.RemoveAt(0);
                    }
                    if (delayedActions.Count != 0)
                        synchronizer.Set();
                }
                Thread.Sleep(1);
            }
        }

        public static void AddTask(Action action, int initializeTime)
        {
            Start();
            lock (syncRoot)
                delayedActions.Add(DateTime.Now.AddMilliseconds(initializeTime), action);
            synchronizer.Set();
        }

        private static void Start()
        {
            if (!started)
            {
                started = true;
                thread.Start();
            }
        }
    }
}
tested and worked correctly, excuse me for my bad english again, i speak spanish, plus in chile it is 5:00 am and i'm a bit tired

Edit: A test i made some mins ago
Code:
using System;
using System.Diagnostics;
using CoreLib.Threading;

namespace ConsoleApplication1
{
    class Foo
    {
        public uint UId { get; set; }

        public void DelayedAction()
        {
            Console.WriteLine("writing UId: {0}, ms elapsed since program start: {1}", UId, Program.sw.ElapsedMilliseconds);
        }
    }
    class Program
    {
        public static Stopwatch sw;
        static void Main(string[] args)
        {
            Console.Title = "Test";
            Foo p1 = new Foo();
            p1.UId = 1;
            Foo p2 = new Foo();
            p2.UId = 2;
            Foo p3 = new Foo();
            p3.UId = 3;
            Foo p4 = new Foo();
            p4.UId = 4;


            //To avoid slower executions because of the jit
            sw = new Stopwatch();
            sw.Start();
            LazyTask.AddTask(p1.DelayedAction, 1000);
            //

            Console.ReadLine();
            Console.Clear();
            sw = new Stopwatch();
            sw.Start();
            LazyTask.AddTask(p1.DelayedAction, 10000);//10 seconds
            LazyTask.AddTask(p2.DelayedAction, 20000);//20 seconds
            LazyTask.AddTask(p3.DelayedAction, 15000);//15 seconds
            LazyTask.AddTask(p4.DelayedAction, 5000);// 5 seconds
            Console.ReadLine();
        }
    }
}
U2_Caparzo is offline  
Old 12/08/2013, 09:41   #2
 
Super Aids's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 1,761
Received Thanks: 950
Make the delayedAction collection a threadsafe collection, because you may add actions to it from multiple threads at the same time.
Super Aids is offline  
Thanks
1 User
Old 12/08/2013, 10:30   #3
 
U2_Caparzo's Avatar
 
elite*gold: 0
Join Date: Aug 2011
Posts: 314
Received Thanks: 90
Quote:
Originally Posted by Super Aids View Post
Make the delayedAction collection a threadsafe collection, because you may add actions to it from multiple threads at the same time.
yeah, i already have that detail in mind, i added the object for the lock but never added the lock itself
U2_Caparzo is offline  
Old 12/08/2013, 11:16   #4
 
elite*gold: 0
Join Date: May 2011
Posts: 648
Received Thanks: 413
Dont forget to sleep your while loop bro, additinally its possible you could make more use of a Stack or Queue instead of a list. Super Aids has a fair point aswell, check what works best for you. Generally speaking that way should be better than those timers
Y u k i is offline  
Old 12/08/2013, 19:43   #5
 
U2_Caparzo's Avatar
 
elite*gold: 0
Join Date: Aug 2011
Posts: 314
Received Thanks: 90
Quote:
Originally Posted by Y u k i View Post
Dont forget to sleep your while loop bro, additinally its possible you could make more use of a Stack or Queue instead of a list. Super Aids has a fair point aswell, check what works best for you. Generally speaking that way should be better than those timers
Hmm good point on the sleep, massive tasks could consume all the processor. I'm using a SortedDictionary because it will sort the collection based on the DateTime that the Action will be invoked, so the first item in the collection always will be the next action that must me invoked, Stacks and queues are unsorted collections
U2_Caparzo is offline  
Old 12/08/2013, 20:24   #6
 
elite*gold: 0
Join Date: Jun 2009
Posts: 787
Received Thanks: 314
You can't use a regular stack or queue. What you need is a priority queue, which is what the SortedList/Dictionary emulates (well, almost. Priority queue implementations generally have O(1) peek, and balanced trees are O(log n)).

Edit for above: I lied, sorted lists are array backed (in increasing order, not heap order), so they do have O(1) peek. But O(n) insert according to MSDN.

The only problem with this approach is this:

I add an event to be processed in 6 minutes. The event loop peeks at this event, sees that the "first" event is to be processed in 6 minutes. Then it waits.

5 seconds from now, I queue up events to be processed in 10 seconds and another in 20 seconds.

When do those get executed?
_tao4229_ is offline  
Old 12/08/2013, 20:46   #7
 
U2_Caparzo's Avatar
 
elite*gold: 0
Join Date: Aug 2011
Posts: 314
Received Thanks: 90
Quote:
Originally Posted by _tao4229_ View Post
You can't use a regular stack or queue. What you need is a priority queue, which is what the SortedList/Dictionary emulates (well, almost. Priority queue implementations generally have O(1) peek, and balanced trees are O(log n)).

Edit for above: I lied, sorted lists are array backed (in increasing order, not heap order), so they do have O(1) peek. But O(n) insert according to MSDN.

The only problem with this approach is this:

I add an event to be processed in 6 minutes. The event loop peeks at this event, sees that the "first" event is to be processed in 6 minutes. Then it waits.

5 seconds from now, I queue up events to be processed in 10 seconds and another in 20 seconds.

When do those get executed?
that was my first problem, that is the reason behind using an autoresetevent instead Thread.Sleep()
Code:
                invokingSynchronizer.WaitOne(nextExecutionTime);//step 1
                if (DateTime.Now.Ticks >= pair.Key.Ticks)//step 2
                {
                    delayedActions.RemoveAt(0);
                    pair.Value();
                }
Lets say that an action must be executed in 6 minutes, the AutoResetEvent will be non-signaled, and the AutoResetEvent will make the thread wait it with a timeout of 6 minutes(step 1), but if a new action is added that must be executed in 10 seconds, it will set the AutoResetEvent to signaled, so the thread will pass inmediately to the step 2, that is why the if was added, if the time has passed it will execute the action, if not, it the cycle will start again, and the Timeout for the AutoResetEvent will be of 10 seconds because the new action will be the first element in the collection.

#Edit:
Reading the code rigth now, it shouldn't work, but it does , however now i'm seeing that there is one useless AutoResetEvent, one will do the job
U2_Caparzo is offline  
Old 12/09/2013, 05:01   #8
 
_DreadNought_'s Avatar
 
elite*gold: 28
Join Date: Jun 2010
Posts: 2,226
Received Thanks: 868
-Indirectly related-

It is nice to see something a little more "upto date" regarding threading around here
_DreadNought_ is offline  
Reply


Similar Threads Similar Threads
PBDO Tasks
07/17/2013 - DarkOrbit - 11 Replies
can some give me some good tasks for pbdo
Delaying some codes
06/24/2013 - CO2 Private Server - 14 Replies
Hello everybody here I want to ask about the best code for delaying some codes I am begginer and I tried some codes like: System.Threading.Thread.Sleep(4000); And like: int Z = 0; DateTime Time = new DateTime(); Time = DateTime.Now; while (Z == 0) {
Help please with pbdo tasks
11/24/2012 - DarkOrbit - 5 Replies
Can anyone help me with this?? Can somebody make me a task for PBDO bot where it kills boss kristallins kristallins and kristollons , collects BB , and uses aegis hp abilies and shield .. On map x-7 i will be really tankfull :)
Need PBDO Tasks
08/21/2012 - DarkOrbit - 4 Replies
Hi all! Can I get some PBDO-bot tasks? I can't use the taskcreator. Shoot npcs on x-2 x-3 x-4, or collect bonusboxes on all maps, etc.. :) Thanks!
Removing Skill Book Delaying With GM Code Very Simple... (Without DIFF + C++ Code.)
05/29/2012 - Metin2 PServer Guides & Strategies - 8 Replies
How2 Enable: Very simple, login with GM char and write this code: /e no_read_delay 1 --------- e = change event flag



All times are GMT +1. The time now is 00:35.


Powered by vBulletin®
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2026 elitepvpers All Rights Reserved.