Когда вызывается myThread.Start (...), есть ли у нас уверенность, что поток запущен? - PullRequest
0 голосов
/ 08 февраля 2010

Когда вызывается myThread.Start (...), есть ли у нас уверенность, что поток запущен? Документация MSDN не совсем об этом. Это говорит о том, что статус изменен на Запуск.

Я спрашиваю, потому что я пару раз видел следующий код. Он создает поток, запускает его, а затем зацикливает, пока статус не станет Выполнен. Это необходимо для цикла?

Thread t = new Thread(new ParameterizedThreadStart(data));
t.Start(data);
while (t.ThreadState != System.Threading.ThreadState.Running &&
       t.ThreadState != System.Threading.ThreadState.WaitSleepJoin)
{
     Thread.Sleep(10);
}

Спасибо!

Ответы [ 3 ]

1 голос
/ 08 февраля 2010

Нет. Thread.Start вызывает «планирование потока для выполнения». Это начнется, но может пройти (короткий) промежуток времени, прежде чем код в вашем делегате действительно запустится. На самом деле, приведенный выше код не делает то, что (я подозреваю) автор также намеревался. Установка для ThreadState потока в ThreadState.Running (что происходит в Thread.Start ) просто гарантирует, что он запланирован для запуска, но ThreadState может быть «Работающим» до того, как делегат фактически выполняется.

Как и предполагал Джон Бергесс , использование ManualResetEvent для уведомления основного потока о том, что поток запущен, является гораздо лучшим вариантом, чем спящий режим и проверка состояния потока.

1 голос
/ 08 февраля 2010

Если у вас установлено значение , а не , позволяющее продолжить цикл до тех пор, пока поток не "запустится", то это будет зависеть от того, что именно вы подразумеваете под "запустил" Означает ли это, что поток был создан ОС и сигнализировал о запуске, но не обязательно, что он сделано еще что-нибудь? Значит ли это, что он выполнил одну или несколько операций?

Хотя это, вероятно, нормально, ваш цикл не является пуленепробиваемым, поскольку теоретически возможно, что весь поток выполняется между временем, когда вы вызываете Start, и когда вы проверяете ThreadState; Также не рекомендуется проверять свойство дважды.

Если вы хотите придерживаться проверки состояния, что-то вроде этого будет / может быть более надежным:

ThreadState state = t.ThreadState;

while(state != ThreadState.Runnung && state != ThreadState.WaitSleepJoin)
{
    Thread.Sleep(10:

    state = t.ThreadState;
}

Однако, это все еще зависит от возможности запуска, запуска и остановки потока, прежде чем вы даже сможете проверить. Да, вы могли бы расширить область действия оператора if, включив в него другие состояния, но я бы рекомендовал использовать WaitHandle для сигнализации, когда поток «запускается».

ManualResetEvent signal;

void foo()
{
    Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));

    signal = new ManualResetEvent();

    t.Start(data);

    signal.WaitOne();

    /* code to execute after the thread has "started" */
}

void ThreadMethod(object foo)
{
    signal.Set();

    /* do your work */
}

У вас все еще есть возможность завершения потока перед проверкой, но вы гарантированно установите WaitHandle после запуска потока. Вызов на WaitOne будет блокироваться на неопределенный срок до тех пор, пока на WaitHandle.

не будет вызван Set.
1 голос
/ 08 февраля 2010

Думаю, это зависит от того, что вы делаете после цикла. Если что-либо последует после того, как оно критически зависит от выполняющегося потока, проверка не является плохой идеей. Лично я бы использовал ManualResetEvent или что-то похожее, что было установлено Thread вместо проверки ThreadStatus

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