Как остановить поток в данной точке? - PullRequest
4 голосов
/ 29 марта 2009

Я пытался остановить некоторые темы, прочитать кое-что о правильном способе сделать это изящно, но я должен сделать что-то не так, потому что это просто не работает. Сначала я попытался без lock() с _IsRunning быть изменчивым, затем попытался с замками. Вот что у меня есть.

private volatile bool _IsRunning;
private static readonly object runLock = new object();

public void Start()
{
    if (_IsRunning == true)
        return;
    _IsRunning = true;
    (new System.Threading.Thread(new System.Threading.ThreadStart(SendLoop))).Start();
}

public void Stop()
{
    lock (runLock)
    {
        _IsRunning = false;
    }
}

private void SendLoop()
{
    while (_IsRunning)
    {
        lock (runLock)
        {
            if (_sockets.Count > 0)
            {
                //some stuff
            }
            else
            {
                System.Threading.Thread.Sleep(10);
            }
        }
    }
}

Я установил точку останова на моем while(), и _IsRunnig все еще остается верным, даже если я передал Stop().

Ответы [ 2 ]

5 голосов
/ 29 марта 2009

Блокировка требуется здесь из-за того, как написан ваш метод запуска, однако вам нужна только блокировка в Start() (где это не сейчас) и Stop(), так как они единственные, которые потенциально может вызвать состояние гонки в вашем случае.

Я бы полностью удалил блокировку из вашего метода SendLoop() (это вызывает DeadLock , поскольку Stop ожидает блокировки для установки _isRunning, а ваш SendLoop удерживает блокировку пока _isRunning не будет установлено в false). Прямо сейчас, когда вы звоните Stop(), блокировка не позволяет ему установить _isRunning = false;

Однако вам понадобятся блокировки в ваших Start() и Stop() методах (если вы не переделываете их структуру полностью). Что-то вроде:

public void Start()
{
    lock (runLock)
    {
        if (_IsRunning == true)
            return;
        _IsRunning = true;
        (new System.Threading.Thread(new System.Threading.ThreadStart(SendLoop))).Start();
    }
}

public void Stop()
{
    lock (runLock)
    {
        _IsRunning = false;
    }
}

Это защитит вас от запуска двух потоков, а также предотвратит остановку Stop до запуска потока.

2 голосов
/ 29 марта 2009

Вам нужно немного реорганизовать свой цикл. Прямо сейчас вы держите блокировку на runLock в течение очень длительного периода времени. Это заставит любого, вызывающего метод Stop, зависать до тех пор, пока не преуспеет блок if или не будет возвращен вызов Sleep. Это может привести к проблемам, потому что вы не можете смотреть на _isRunning при вызове метода Stop, только когда он возвращается. Попробуйте реорганизовать ваш код следующим образом

private void SendLoop() {
  do {
    if ( _sockets.Count > 0 ) {
    } else { 
      System.Threading.Thread.Sleep(10);
    }
    bool shouldContinue;
    lock ( runLock ) { 
      shouldContinue = _IsRunning;
    }
  while(shouldContinue);
}

Я не уверен на 100%, что это проблема. Но, по крайней мере, это должно немного прояснить ситуацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...