Results 1 to 6 of 6
  1. #1

    Non-blocking timer

    I was wondering what is recommended for non-blocking delays in procon? Like when you want to delay a message or something from running by a few seconds.

    I have two different ideas but was wondering what you guys thought?

    Code:
                
    ThreadPool.QueueUserWorkItem((state) =>
                {
                    Thread.Sleep(1000);
                    Test("Hello World!!!");
                });
    or

    Code:
     
    Delay(2000, (sender, e) => {
                    Test("HHHHHHhhhhhiiiiiiiiii");
                    KillTimer(sender);
                });
    
     public static void Delay(int interval, ElapsedEventHandler d)
            {
                System.Timers.Timer t = new System.Timers.Timer();
                t.Interval = interval;
                t.AutoReset = false;
                t.Elapsed += d;            
                t.Start();
            }
    
    public static void KillTimer(Object sender)
            {
                var t = (System.Timers.Timer)sender;
                t.Stop();
                t.Dispose();
            }
    Do you guys have any suggestions on how to do this properly?

  2. #2
    I have a way of doing this in AdKats. Works great. I'll comment with it tonight.
    ____

  3. #3
    Looking at your code mine is basically the first one, differences between that and mine aren't that large, just using thread/delegate.

    EDIT: I guess a larger difference is that i monitor all of the threads, so i know if something has gone wrong and a thread doesn't close. I'll still comment with the code tonight.
    ____

  4. #4
    ok thanks

  5. #5
    Not sure if it will help, but here is what i have.

    Code:
    Basic structure of what i do:
    
    
    var deferredAction = new Thread(new ThreadStart(delegate
    {
    	Thread.CurrentThread.Name = "MyDeferredAction";
    	Thread.Sleep(TimeSpan.FromSeconds(10));
    	
    	//Do 10 second deferred action
    }));
    deferredAction.Start();
    
    
    But the problem is monitoring your threads. I use threads for basically everything, 9 main threads running most of the time and helper threads for each action, so it's nice to have a monitor for everything.
    
    
    //How to start the action once everything is set up:
    
    
    StartAndLogThread("MyUniqueDeferredAction", new Thread(new ThreadStart(delegate
    {
    	Thread.CurrentThread.Name = "MyUniqueDeferredAction";
    	Thread.Sleep(TimeSpan.FromSeconds(10));
    	
    	//Do 10 second deferred action
    	
    	LogThreadExit();
    })));
    
    
    //The system behind it
    
    
    private readonly Dictionary<Int32, Thread> _aliveThreads = new Dictionary<Int32, Thread>();
    
    
    protected void StartAndLogThread(String name, Thread aThread)
    {
    	aThread.Start();
    	lock (_aliveThreads)
    	{
    		//If a thread name is passed in, make sure no other threads are already running with that name
    		if ((String.isNullOrEmpty(name) || _aliveThreads.Values.Any(aThread => aThread.Name == name)) &&
    		    !_aliveThreads.ContainsKey(aThread.ManagedThreadId))
    		{
    			_aliveThreads.Add(aThread.ManagedThreadId, aThread);
    			Thread.Sleep(50);
    		}
    	}
    }
    
    
    protected void LogThreadExit()
    {
    	lock (_aliveThreads)
    	{
    		_aliveThreads.Remove(Thread.CurrentThread.ManagedThreadId);
    	}
    }
    
    
    // I have one monitor thread that never ends, and in it I run this every 30 seconds to watch for dead/stale threads
    
    
    
    
    //Clean dead threads
    foreach (Int32 deadThreadID in _aliveThreads.Values.ToList().Where(thread => !thread.IsAlive).Select(thread => thread.ManagedThreadId))
    {
    	_aliveThreads.Remove(deadThreadID);
    }
    //Check for thread warning
    if (_aliveThreads.Count() >= 20)
    {
    	String aliveThreads = "";
    	lock (_aliveThreads)
    	{
    		foreach (Thread value in _aliveThreads.Values.ToList())
    		{
    			aliveThreads = aliveThreads + (value.Name + "[" + value.ManagedThreadId + "] ");
    		}
    	}
    	Log.Warn("Thread warning: " + aliveThreads);
    }
    
    
    
    
    // On plugin shutdown I check for threads still exiting, and wait for them all to end before allowing full plugin shutdown
    
    
    //Check to make sure all threads have completed and stopped
    Int32 attempts = 0;
    Boolean alive = false;
    do
    {
    	OpenAllHandles();
    	attempts++;
    	Thread.Sleep(500);
    	alive = false;
    	String aliveThreads = "";
    	lock (_aliveThreads)
    	{
    		foreach (Int32 deadThreadID in _aliveThreads.Values.Where(thread => !thread.IsAlive).Select(thread => thread.ManagedThreadId).ToList())
    		{
    			_aliveThreads.Remove(deadThreadID);
    		}
    		foreach (Thread aliveThread in _aliveThreads.Values.ToList())
    		{
    			alive = true;
    			aliveThreads += (aliveThread.Name + "[" + aliveThread.ManagedThreadId + "] ");
    		}
    	}
    	if (aliveThreads.Length > 0)
    	{
    		if (attempts > 20)
    		{
    			Log.Warn("Threads still exiting: " + aliveThreads);
    		}
    		else
    		{
    			Log.Debug(() => "Threads still exiting: " + aliveThreads, 2);
    		}
    	}
    } while (alive);
    ____

  6. #6
    Thanks for the info.

    I have been using the threadpool for quick tasks because it handles the threads for me mostly. I may need some monitoring on my longer running threads.

 

 

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •