What is the best way to delay a console application for a few seconds

14,488

Solution 1

I am not totally sure what you're after. Do you want to be able to temporarily stop all new calls to RunInPlayBettingControl method? If yes then you must do threads synchronization. Do it like that:

class XYZ
{
  Object syncObj = new Object();
  ...

  public void RunInPlayBettingControl(int SystemPK,string betfairLogon, string betfairPassword, string systemName, int RacePK)
  {
    lock(this.syncObj)
    { }
    ...

    switch(...)
    {
      ...
      case 2:
      // race is in play but not over our marker yet so go back in after a short wait
      lock(this.syncObj)
      {
          Thread.Sleep(1000);
      }
      ...
    }
  }
}

This way you will hold any new calls to RunInPlayBettingControl but running ones will finish.

Is this any helpful?

Generally though you should avoid calling Thread.Sleep because during that time thread is in lock wait state and it would prevent application from exiting (unless it is background thread).

Solution 2

Thread.Sleep(2500);

But this doesn't wait at all and the betting proc is called instantly again without waiting.

Thread.Sleep() will suspend the current thread for the specified time. What you are seeing is other threads executing the same method (I assume you have a breakpoint there for checking), since you spawned a bunch of them with Parallel.ForEach().

Share:
14,488
Monkey Magix
Author by

Monkey Magix

Web developer for far too long.

Updated on June 04, 2022

Comments

  • Monkey Magix
    Monkey Magix almost 2 years

    Overview.

    I have a Windows Service written in C# .NET 4.0 that is hooking into the Betfair API to place bets automatically (all betting decisions are done in the SQL DB). The service has a number of timers that sets up some polling for 3 main areas (place pending bets, check prices, place in play bets [during the race]). The timers are all triggered every 30 seconds.

    The one I am having difficulty with is the InPlay betting one. Once every 30 seconds the timer calls a method in my BetfairBot object that checks for upcoming races that have inplay bets for them. There could be multiple systems betting on the same race so I wanted to fire off the "control" method in parrallel so one system isn't waiting for the other to finish before being able to place its bets.

    So I have some code like this to fire off the parallel control methods

    // some SQL to get my upcoming races
    DataTable sqlRecordset = this.dataAccess.GetDataTable(SQL);
    
    try
    {
    
    // run in parallel for each system and concurrent races
    
    Parallel.ForEach(sqlRecordset.AsEnumerable(), recordsetRow =>
    {
    
        betfairLogon = recordsetRow["BetfairLogon"].ToString();
        betfairPassword = recordsetRow["BetfairPassword"].ToString();
        SystemPK = Convert.ToInt32(recordsetRow["SystemPK"]);
        systemName = recordsetRow["SystemName"].ToString();
        RacePK = Convert.ToInt32(recordsetRow["RaceFK"]);
    
        // spawn thread for each system    
        this.RunInPlayBettingControl(SystemPK, betfairLogon, betfairPassword, systemName, RacePK);
    
    });
    
    
    }
    catch (Exception e)
    {
    // log error
    HelperLib.LogMsg("Error starting Parallel Threads for RacePK: " + RacePK.ToString() + " - " +e.Message.ToString());
    }
    

    Then in my control method I loop until the betting is over, calling another method which handles the betting and returns a result code telling my system the status of the betting eg whether the race has finished, not started yet, or just about to start.

    On a couple of these statuses I want to delay my thread for a couple of seconds before re-calling the betting method.

    I have tried

    Thread.Sleep(2500);
    

    But this doesn't wait at all and the betting proc is called instantly again without waiting.

    I have read up a bit about threading and I don't know whether the problem is with my Parallel loop that triggers parallel calls to my control method (which needs to delay the thread on demand) or with my control method and the Thread.Sleep(delay) call.

    My initial timers that are in the Service class work fine and I don't know the best way of going about this or what the problem is with the delaying as I presumed each Thread initiated by the Parallel loop would be running on its own and therefore delayed with a .Sleep call if required.

    Should I use more timers OR another method, and what is the best way with my existing loop code?

    The Control method fired by the Parallel loop is below. The code for the actual betting method is too complicated to post here but it has no thread calls just some SQL and some calls to the Betfair API.

    Any help would be much appreciated. Thanks in advance.

    public void RunInPlayBettingControl(int SystemPK,string betfairLogon, string betfairPassword, string systemName, int RacePK)
    {
    int result = 0;
    bool quit = false; // we loop until true
    
    // decode our encrypted logon details
    betfairPassword = HelperLib.GetPassword(betfairLogon);
    betfairLogon = HelperLib.DecodeLogon(betfairLogon);
    
    // create API object
    this.betfairAPI = new BetfairAPI(systemName);
    
    // try and log in for this system and save the session for future use
    
    if (!String.IsNullOrEmpty(betfairLogon) && !String.IsNullOrEmpty(betfairPassword))
    {
    
    // check logged in status as we might have used previous session otherwise log in now
    if (!this.betfairAPI.IsLoggedIn() && this.betfairAPI.Login(betfairLogon, betfairPassword) == false)
    {
        // couldnt login so exit
        return;
    }
    else
    {                  
    
        // save session to file
        this.betfairAPI.SaveSession(systemName);
    
        // we loop until we know there is no more point in doing so
        while (!quit)
        {
        // result code values
        // 0 = We have no idea whats going on yet
        // 1 = Race is actually closed/finished so exit
        // 2 = Race is inplay but we are not ready to bet yet - wait a short while
        // 3 = Race is inplay and ready to bet
        // 4 = Race is not inplay yet so wait a bit and carry on
    
        // this is our main betting method that handles all our betting
        result = this.RunInPlayBetting(SystemPK, betfairLogon, betfairPassword, systemName, RacePK);
    
        // check result to see if we quit looping
        switch (result)
        {
            case 1:
            // race is over so exit
            quit = true;
            break;
            case 2:
            // race is in play but not over our marker yet so go back in after a short wait
             Thread.Sleep(1000);  // NOT WORKING
            quit = false;
    
            break;
            case 3:
            // race is in play so lets go straight back in and try some more betting
            quit = false; 
            break;
            case 4:
            // not in play yet so keep looping after a short wait
            quit = false;
    
            Thread.Sleep(2500); // NOT WORKING
    
            break;
    
            case 0:
            // have no idea whats going just quit loop
            quit = true;
            break;
    
        }
        }
    }
    
    }   
    
    return;
    }