Как лучше всего отложить консольное приложение на несколько секунд? - PullRequest
2 голосов
/ 30 января 2012

Обзор.

У меня есть служба Windows, написанная на C # .NET 4.0, которая подключается к API Betfair для автоматического размещения ставок (все решения по ставкам принимаются в БД SQL).У службы есть несколько таймеров, которые устанавливают некоторые опросы для 3 основных областей (делайте ставки в ожидании, проверяйте цены, делайте ставки в игре [во время гонки]).Все таймеры срабатывают каждые 30 секунд.

У меня возникли трудности с ставками InPlay.Раз в 30 секунд таймер вызывает метод в моем объекте BetfairBot, который проверяет предстоящие гонки, в которых есть ставки на игру.Может быть несколько систем, делающих ставки на одну и ту же гонку, поэтому я хотел включить параллельный «контрольный» метод, чтобы одна система не дожидалась, пока другая закончит, прежде чем она сможет делать свои ставки.

ИтакУ меня есть такой код для запуска параллельных методов управления

// 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());
}

Затем в моем методе управления я зацикливаюсь до окончания ставок, вызывая другой метод, который обрабатывает ставки и возвращает код результата, сообщающий моей системестатус ставок, например, закончилась ли гонка, еще не началась или вот-вот начнется.

В некоторых из этих статусов я хочу на несколько секунд задержать свою нить, прежде чем повторно вызватьметод ставок.

Я пытался

Thread.Sleep(2500);

Но это совсем не ждет, и процедура ставок снова вызывается мгновенно, без ожидания.

Я прочиталнемного о многопоточности, и я не знаю, связана ли проблема с моим параллельным циклом, который вызывает параллельные вызовы моего метода управления (который требуетs, чтобы задержать поток по требованию) или с моим методом управления и вызовом Thread.Sleep (delay).

Мои начальные таймеры в классе Service работают нормально, и я не знаю лучшего способаЕсли говорить об этом или в чем проблема с задержкой, так как я предполагал, что каждый поток, инициируемый циклом Parallel, будет работать сам по себе и, следовательно, будет задерживаться вызовом .Sleep, если потребуется.

Должен ли я использовать больше таймеров ИЛИдругой метод, и как лучше всего использовать мой существующий код цикла?

Ниже приведен метод управления, запускаемый параллельным циклом.Код для действующего метода ставок слишком сложен, чтобы публиковать здесь, но в нем нет вызовов потоков, только некоторые SQL и некоторые вызовы API Betfair.

Любая помощь будет принята с благодарностью.Заранее спасибо.

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;
}

Ответы [ 2 ]

3 голосов
/ 30 января 2012

Thread.Sleep (2500); * +1002 *

Но это совсем не ждет, и процесс ставок вызывается мгновенно снова без ожидания.

Thread.Sleep() приостановит поток current на указанное время. То, что вы видите, это другие потоки, выполняющие тот же метод (я предполагаю, что у вас есть точка останова для проверки), так как вы породили кучу из них с помощью Parallel.ForEach().

1 голос
/ 02 февраля 2012

Я не совсем уверен, что вы ищете. Хотите иметь возможность временно остановить все новые вызовы метода RunInPlayBettingControl? Если да, то вы должны выполнить синхронизацию потоков. Сделай так:

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);
      }
      ...
    }
  }
}

Таким образом, вы будете удерживать любые новые вызовы RunInPlayBettingControl, но выполнение будет завершено.

Это полезно?

Как правило, следует избегать вызова Thread.Sleep, поскольку в течение этого времени поток находится в состоянии ожидания блокировки, и это не позволит приложению завершиться (если только это не фоновый поток).

...