2013-04-17 2 views
1

У меня есть основной поток, который управляет формой окна, при нажатии кнопки выполняются два потока. Один используется для записи информации, другой используется для его чтения. Идея положить их в потоки - это позволить пользователю взаимодействовать с интерфейсом во время выполнения.Запуск двух потоков запускает их последовательно и не в одно и то же время

Вот создание двух потоков;

Thread recordThread = new Thread(() => RecordData(data)); 
recordThread.Name = "record"; 
recordThread.Start(); 

Thread readThread = new Thread(() => ReadData(data)); 
readThread.Name = "read"; 
readThread.Start(); 

В данные просто данных объект, который хранит данные, записанные во время записи.

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

Я пытался решить это в течение нескольких часов, и я не могу понять, почему он это сделает. Добавление a;

while(readThread.IsAlive) { } 

сразу после начала приостановит выполнение чего-либо после этого, и это состояние Запуск. Но это не будет идти к данному методу.

Любые идеи?

Редактировать: Две функции, вызываемые потоками;

private void RecordData(Data d) 
    { 
     int i = 0; 
     while (i < time * freq) 
     { 
      double[] data = daq.Read(); 
      d.AddData(data); 
      i++; 
     } 
    } 

    private void ReadData(Data d) 
    { 
     UpdateLabelDelegate updateData = 
      new UpdateLabelDelegate(UpdateLabel); 

     int i = 0; 
     while (i < time * freq) 
     { 
      double[] data = d.ReadLastData(); 
      this.Invoke(updateData, new object[] { data }); 
      i++; 
     } 
    } 

данные объект имеет замок в обеих функций, которые призваны; ReadLastData и Read.

Вот методы в Данные объект.

public void AddData(double[] data) 
    { 
     lock (this) 
     { 
      int i = 0; 
      foreach (double d in data) 
      { 
       movementData[i].Add(d); 
       i++; 
      } 
     } 
    } 

    public double[] ReadLastData() 
    { 
     double[] data = new double[channels]; 
     lock (this) 
     { 
      int i = 0; 
      foreach (List<double> list in movementData) 
      { 
       data[i] = list[list.Count - 1]; 
      } 
     } 
     return data; 
    } 
+2

Это зависит от того, ожидает ли второй поток ресурс, заблокированный первым потоком (угадывание 'данных'). Какой замок у вас есть? – Belogix

+3

Пожалуйста, покажите короткую, но * полную * программу, демонстрирующую проблему. –

+2

Пожалуйста, покажите больше кода, этого недостаточно –

ответ

1

ВЫГЛЯДИТ как у вас есть состояние гонки между чтением/письмом. В первом потоке вы блокируете объект, пока вы добавляете в него данные, а во втором - вы делаете попытку, чтобы получить эксклюзивную блокировку, чтобы начать чтение. Однако проблема в том, что первый поток выполняется так быстро, что второй поток никогда не получает шанс получить блокировку.

Решение этой проблемы действительно зависит от того, какое поведение вы здесь находитесь. Если вы ожидаете, что после каждой записи вы получите последовательное чтение, то вам нужно будет контролировать выполнение операций чтения/записи, например.

static AutoResetEvent canWrite = new AutoResetEvent(true); // default to true so the first write happens 
static AutoResetEvent canRead = new AutoResetEvent(false); 
... 
private void RecordData(Data d) 
{ 
    int i = 0; 
    while (i < time * freq) 
    { 
     double[] data = daq.Read(); 
     canWrite.WaitOne(); // wait for the second thread to finish reading 
     d.AddData(data); 
     canRead.Set(); // let the second thread know we have finished writing 
     i++; 
    } 
} 

private void ReadData(Data d) 
{ 
    UpdateLabelDelegate updateData = 
     new UpdateLabelDelegate(UpdateLabel); 

    int i = 0; 
    while (i < time * freq) 
    { 
     canRead.WaitOne(); // wait for the first thread to finish writing 
     double[] data = d.ReadLastData(); 
     canWrite.Set(); // let the first thread know we have finished reading 
     this.Invoke(updateData, new object[] { data }); 
     i++; 
    } 
} 
+0

Это, похоже, решило вопрос об обстреле функций! Ницца! Единственная проблема заключалась в том, что это заставило мою систему не функционировать должным образом из-за того, что она сейчас слишком медленная. Я начну испытывать с ним чтение каждого десятого значения или около того. Но это еще одна проблема, это решение этого вопроса. Благодаря! – Sander

+0

@Sander, что именно вам нужно? Вы действительно хотите, чтобы чтение было во время записи? Просто FYI в отношении использования [оператора блокировки] (http://msdn.microsoft.com/en-gb/library/c5kehkcz (v = vs.80) .aspx) - не рекомендуется сами блокировать типы, т. Е. lock (this) 'нарушает рекомендации. Вместо этого вы должны иметь объект блокировки, внешний по отношению к вашему * data * экземпляру (подобно тому, как я использую 'AutoResetEvent' в моем примере). На самом деле вы можете найти, что основная проблема здесь. – James

+0

Изменив код на то, что вы рекомендовали, он работал, как я уже говорил, только он слишком медленный. Я хочу сделать, чтобы получить данные в реальном времени с карты сбора данных и представить их пользователю.Вот почему я хочу читать данные во время записи. Информация, которую я получаю из записи, важнее, чем чтение, поэтому я должен выяснить, как я должен расставить приоритеты записи по чтению. – Sander

0

Не могли бы вы попробовать добавить спать в RecordData? Возможно, это просто ваша операционная система Windows (mono cpu ??), которая не позволяет второму потоку получить доступ к ресурсам процессора.

Не делайте этого: замок (это)

ли что-нибудь подобное вместо:

private object oLock = new object(); 

[...] 

lock (this.oLock) 

EDIT: Не могли бы вы попробовать звонки, как это:

Thread recordThread = new Thread((o) => RecordData((Data)o)); 
recordThread.Name = "record"; 
recordThread.Start(data); 
+0

Я запускаю систему с 4 ядрами. И что касается моего понимания, то несколько потоков должны работать даже на одном ядре. Но в любом случае, в моем случае это действительно должно быть не проблема. (Изменить: забыл «нет») – Sander

+0

Okey, спасибо. Но проблема сохраняется. – Sander

+0

событие с заменой oLock? :/ – Serge

Смежные вопросы