Jump to content

Recommended Posts

i have some external script code that launch new Thread() or subscribe on wrobot events (Fight events or MoveEvents as example) and i need it to run during whole profle.

that profile loads next profile and next profile use same script code that launch new Thread() or subscribe events.

i cannot stop threads/unsubscribe events from previous profile and loadeded profile run new one.

i know new profile loaded and compiled at runtime when loaded.

thats why i have two questions:

1. previous profile compiled code unloaded? what happend to event subscribers/threads i need to stop/unsubscribe or when old profile code unloaded event listeners/thread destroyed too?

2. if previous profile code still run, is there wrobot events that fires before profile unloaded to allow me stop threads and unsubscribe events ?


@Droidz
 

Hello, if you start a thread it will persist till you abort it. That means if you load a profile with a starting thread you need to save it somewhere to abort it later (it's more easily if it's on the same instance).

For this purpose you can use a thread manager like this:

        public class ThreadManager
        {
            public int TableId = 1;
            Dictionary<string, Thread> _threads = new Dictionary<string, Thread>();

            public void Start(Action method, string threadName)
            {
                if (!_threads.ContainsKey(threadName))
                {
                    Thread Thread = new Thread(() => method());
                    Thread.Name = Convert.ToString(TableId);
                    Thread.Start();
                    _threads.Add(threadName, Thread);
                    log("Start Thread " + method.Method.Name + ".");
                }
                else
                {
                    log("Thread " + method.Method.Name + " already executed.");
                }
            }

            public void Start(Action method)
            {
                if (!_threads.ContainsKey(method.Method.Name))
                {
                    Thread Thread = new Thread(() => method());
                    Thread.Name = Convert.ToString(TableId);
                    Thread.Start();
                    _threads.Add(method.Method.Name, Thread);
                    log("Start Thread " + method.Method.Name + ".");
                }
                else
                {
                    log("Thread " + method.Method.Name + " already executed.");
                }
            }

            public void Abort(string threadName)
            {
                if (_threads.ContainsKey(threadName))
                {
                    _threads[threadName].Abort();
                    _threads.Remove(threadName);
                    log("Abort Thread " + threadName + ".");
                }
            }

            public void Abort(Action method)
            {
                if (_threads.ContainsKey(method.Method.Name))
                {
                    _threads[method.Method.Name].Abort();
                    _threads.Remove(method.Method.Name);
                    log("Abort Thread " + method.Method.Name + ".");
                }
            }
        }

 

but this one can only handle methods with return type void (if you want more you need func<>) that would perfectly fit if a event exist.

But the question is what if not? How do you abort it, if you have started the new profile/thread while "Dictionary<string, Thread> _threads = new Dictionary<string, Thread>();" is new initialized?

For this purpose you could use System.Runtime.Caching.MemoryCache to save your thread on memory to access it later & abort it like this:

 

    public class CacheManager
    {
        public void SaveTocache(string cacheKey, object savedItem, DateTime absoluteExpiration)
        {
            if (!IsIncache(cacheKey))
            {
                MemoryCache.Default.Add(cacheKey, savedItem, absoluteExpiration);
            }
            else
            {
                MemoryCache.Default.Set(cacheKey, savedItem, absoluteExpiration);
            }
        }

        public T GetFromCache<T>(string cacheKey) where T : class
        {
            return MemoryCache.Default[cacheKey] as T;
        }

        public void RemoveFromCache(string cacheKey)
        {
            MemoryCache.Default.Remove(cacheKey);
        }

        public bool IsIncache(string cacheKey)
        {
            return MemoryCache.Default[cacheKey] != null;
        }
    }
    
    public class ThreadManager
    {
        public int TableId = 1;
        public CacheManager CacheManager_ = new CacheManager();
        Dictionary<string, Thread> _threads = new Dictionary<string, Thread>();


        public void Start(Action method, string threadName, bool cache = false, DateTime cacheExpiration = default(DateTime))
        {
            if (!cache)
            {
                if (!_threads.ContainsKey(threadName))
                {
                    Thread Thread = new Thread(() => method());
                    Thread.Name = Convert.ToString(TableId);
                    Thread.Start();
                    _threads.Add(threadName, Thread);
                    Logging.Write("Start Thread " + threadName + ".");
                }
                else
                {
                    Logging.Write("Thread " + threadName + " already executed.");
                }
            }
            else
            {
                if (!CacheManager_.IsIncache(threadName))
                {
                    Thread Thread = new Thread(() => method());
                    Thread.Name = Convert.ToString(TableId);
                    Thread.Start();
                    if (cacheExpiration == default(DateTime))
                    {
                        CacheManager_.SaveTocache(threadName, Thread, DateTime.Now.AddMinutes(30));
                        Logging.Write("Start Thread " + threadName + ".\nExpires at " + DateTime.Now.AddMinutes(30));
                    }
                    else
                    {
                        CacheManager_.SaveTocache(threadName, Thread, cacheExpiration);
                        Logging.Write("Start Thread " + threadName + ".\nExpires at " + cacheExpiration);
                    }
                }
                else
                {
                    Logging.Write("Thread " + threadName + " already executed.");
                }
            }
        }

        public void Start(Action method, bool cache = false, DateTime cacheExpiration = default(DateTime))
        {
            if (!cache)
            {
                if (!_threads.ContainsKey(method.Method.Name))
                {
                    Thread Thread = new Thread(() => method());
                    Thread.Name = Convert.ToString(TableId);
                    Thread.Start();
                    _threads.Add(method.Method.Name, Thread);
                    Logging.Write("Start Thread " + method.Method.Name + ".");
                }
                else
                {
                    Logging.Write("Thread " + method.Method.Name + " already executed.");
                }
            }
            else
            {
                if (!CacheManager_.IsIncache(method.Method.Name))
                {
                    Thread Thread = new Thread(() => method());
                    Thread.Name = Convert.ToString(TableId);
                    Thread.Start();
                    if (cacheExpiration == default(DateTime))
                    {
                        CacheManager_.SaveTocache(method.Method.Name, Thread, DateTime.Now.AddMinutes(30));
                        Logging.Write("Start Thread " + method.Method.Name + ".\nExpires at " + DateTime.Now.AddMinutes(30));
                    }
                    else
                    {
                        CacheManager_.SaveTocache(method.Method.Name, Thread, cacheExpiration);
                        Logging.Write("Start Thread " + method.Method.Name + ".\nExpires at " + cacheExpiration);
                    }
                }
                else
                {
                    Logging.Write("Thread " + method.Method.Name + " already executed.");
                }
            }
        }

        public void Abort(string threadName, bool cache = false)
        {
            if (!cache)
            {
                if (_threads.ContainsKey(threadName))
                {
                    _threads[threadName].Abort();
                    _threads.Remove(threadName);
                    Logging.Write("Abort Thread " + threadName + ".");
                }
            }
            else
            {
                if (CacheManager_.IsIncache(threadName))
                {
                    CacheManager_.GetFromCache<Thread>(threadName).Abort();
                    CacheManager_.RemoveFromCache(threadName);
                    Logging.Write("Abort Thread " + threadName + ".");
                }
                else
                {
                    Logging.Write("Thread " + threadName + "could not be found in cache.");
                }
            }
        }

        public void Abort(Action method, bool cache = false)
        {
            if (!cache)
            {
                if (_threads.ContainsKey(method.Method.Name))
                {
                    _threads[method.Method.Name].Abort();
                    _threads.Remove(method.Method.Name);
                    Logging.Write("Abort Thread " + method.Method.Name + ".");
                }
            }
            else
            {
                if (CacheManager_.IsIncache(method.Method.Name))
                {
                    CacheManager_.GetFromCache<Thread>(method.Method.Name).Abort();
                    CacheManager_.RemoveFromCache(method.Method.Name);
                    Logging.Write("Abort Thread " + method.Method.Name + ".");
                }
                else
                {
                    Logging.Write("Thread " + method.Method.Name + "could not be found in cache.");
                }
            }
        }
    }

But keep in mind that the thread is still executed even if it expires in the cache. In the end you can access the thread to abort it even from your new thread now.

And yes it would be easier if an event exist to manage your current profile/thread but i haven't found the correct one :) but i had these snippets already on my disk.

I hope that it can help you.

got your point. i just have tons of profiles. i just want to avoid puting at end of each profile code to stop threads and unsubscribe events.

there more simple way to do that.

public static class ProfileUnload
{
  public static Event OnProfileUnload;
  
  public static void FireEvent()
  {
   if (OnProfileUnload != null)
     OnProfileUnload():
  }
}

and insert RunCode at end of each profile "ProfileUnload.FireEvent();"

and after that i can subscribe on profile end event and stop thread and unsubscribe from other wrobot events. i just want to avoid mass profile editing

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...