Странная проблема с использованием потоков

#c# #multithreading

#c# #многопоточность

Вопрос:

Я использую поток для запуска общедоступной функции класса. Проблема в том, что только если установлена точка останова внутри функции потока (общедоступная функция класса), она вызывается иначе, вызывая поток.Запуск не оказывает никакого эффекта. После вызова функции потока она успешно завершается, давая желаемые результаты.

  QueueProcessor     processor  = null;
 Thread subprocess =null;

 public void processQueue()
 {
    if (processor == null)
    {         
        processor = new QueueProcessor();
    }

    if (subprocess == null)
    {                                            
        subprocess = new Thread(processor.run);
        subprocess.IsBackground = true;
    }

    if (!subprocess.IsAlive)
    {                
        subprocess.Start();                                
    }
    else
    {          
    }
} 

class QueueProcessor
{       
    public QueueProcessor()
    {           
        instance = new RecordDao();
        service = new CommonsService();
    }

    public void run()
    {
        startProcessing(); // it won't reach here unless a breakpoint is set.
    }

    public bool startProcessing()
    {
        //some database routines here.

       // some web service calls here
    }
}
  

Пожалуйста, помогите.

Комментарии:

1. THIS IS ALWAYS FALSE IN SOME CASES ???

2. На самом деле, «Всегда false в некоторых случаях» имеет для меня смысл — в некоторых тестовых прогонах subProcess.IsAlive оно остается false навсегда; в других тестовых прогонах это иногда false.

3. Как вы думаете, почему этот код не выполняется? Вы выполняете очень мало работы в своем потоке. Вы уверены, что он не был завершен до вашей проверки IsAlive?

4. Извините, ребята, удалено Всегда false

Ответ №1:

РЕДАКТИРОВАТЬ: теперь, когда вы изменили код, есть две проблемы:

  1. Вы потенциально пытаетесь перезапустить поток, если вы когда-либо вызываете processQueue после завершения обработки. Вы не можете этого сделать.

  2. Если processQueue вызывается из нескольких потоков, у вас возникают проблемы с потенциальным запуском нескольких потоков из-за условий гонки, а также потенциальных проблем с моделью памяти.

Первый пункт проще решить с помощью:

 if (subprocess == null || !subprocess.IsAlive)
{                                            
    subprocess = new Thread(processor.run);
    subprocess.IsBackground = true;
    subprocess.Start();
}
  

… но это все еще оставляет потенциальную проблему второго пункта. Что такое вызов processQueue ? Это всегда один и тот же поток? (И почему вы игнорируете.Соглашения об именовании сетей?)

Я предполагаю, что то, что вы видите, на самом деле обработка происходит ровно один раз, но нет никакой работы, и будущие вызовы не перезапускают поток, как предположительно вы ожидали, — тогда как, если у вас есть точка останова, то к тому времени, когда вы снова нажмете «перейти», есть над чем поработать. На предположение … конечно, запуск потока работает без точек останова, поэтому недостаток где-то в вашем коде. Если бы вы могли создать короткую, но полную программу, которая демонстрирует проблему, мы могли бы разобраться в ней.


Ваш поток почти ничего не делает, поэтому вполне разумно завершить поток до того, как он достигнет while цикла. Дело не в том, что он не запускается, а в том, что он запускается, а затем немедленно завершается.

В качестве альтернативы, у вас может быть такой поток выполнения:

 Main thread                  New thread status

                             Not started...

Check: IsAlive == false

                             Still not started...

Check: IsAlive == false

                             Starting!
                             Call startProcessing...
                             startProcessing completes...
                             Finished

Check: IsAlive == false
  

Поток выполняется без проблем, но IsAlive всегда имеет значение false.

Непонятно, почему у вас есть этот код в первую очередь — чего вы пытаетесь достичь?

Комментарии:

1. Правильно. Поток еще не «активен», когда свойство проверяется.

2. @GlennFerrieLive: еще не жив или уже не жив . В том, что касается свойства, нет никакой разницы IsAlive .

3. На самом деле функция потока выполняет некоторые сложные функции базы данных и вызовы веб-служб. Я не публиковал его здесь, поскольку он содержит много внешних зависимостей. Никогда не думал об этой лазейке. Обновил код, добавив комментарий // некоторые процедуры базы данных здесь.

4. Обновлен код, чтобы удалить проверку IsAlive.. Похоже, это создает здесь путаницу. Спасибо

Ответ №2:

Итак, проблема в том, что processor.run соответствует сигнатуре для параметра потока, но это неверно, поэтому поток никогда не получает допустимую функцию, поэтому он никогда не запускается. Функция, которую выполняет поток, должна быть статической функцией, и в этом случае я бы переместил поток в объект классов обработки.

Комментарии:

1. но он вызывает ту же функцию потока в тех случаях, когда я устанавливаю точку останова. Спасибо

2. В вашем примере кода на моей машине он никогда не вызывает его. Вы уверены, что что-то еще не вызывает это? Может быть, вы работаете над проектом, и пример полностью совпадает с проектом?

3. Нет, он вызывается только из одного места. Спасибо