заблокировать общие данные с помощью c # - PullRequest
6 голосов
/ 27 апреля 2010

У меня есть программа (C #) со списком тестов, которые нужно сделать.
Также у меня есть два потока. один для добавления задачи в список, а другой для чтения и удаления из него выполненных задач.
Я использую функцию блокировки каждый раз, когда один из потоков хочет получить доступ к списку.
Еще одна вещь, которую я хочу сделать, если список пуст, поток, который должен прочитать из списка, будет спать. и просыпаться, когда первый поток добавляет задачу в список. Вот код, который я написал:

...
List<String> myList = new List();
Thread writeThread, readThread;
writeThread = new Thread(write);
writeThread.Start();
readThraed = new Thread(read);
readThread.Start();
...
private void write()
{
   while(...)
   {
     ...
     lock(myList)
     {
        myList.Add(...);
     }
     ...
     if (!readThread.IsAlive)
     {
        readThraed = new Thread(read);
        readThread.Start();
     }
     ...
   }
   ...
}

private void read()
{
bool noMoreTasks = false;
   while (!noMoreTasks)
   {
      lock (MyList)//syncronize with the ADD func.
      {
                if (dataFromClientList.Count > 0)
                {
                    String task = myList.First();
                    myList.Remove(task);
                }
                else
                {
                    noMoreTasks = true;
                }      
      }
      ...
   }
   readThread.Abort();
}

Очевидно, я сделал это неправильно, и он не работает должным образом (readTread не читает из списка).
Кто-нибудь знает в чем моя проблема и как ее исправить?
Большое спасибо,

Ответы [ 2 ]

3 голосов
/ 27 апреля 2010

Вам нужна очередь блокировки. Это похоже на обычную очередь, за исключением блоков метода Dequeue, если в очереди ничего нет. Здесь - это одна реализация. Как только вы внедрили очередь блокировки, все остальное легко. Просто будьте осторожны, какую реализацию очереди блокировки вы используете. Я видел множество примеров, в которых есть тонкие проблемы с потоками. Возможно, лучше придерживаться предоставленной мной ссылки.

public class Example
{
  private BlockingQueue<Task> m_Queue = new BlockingQueue<Task>();

  public void StartExample()
  {
    Thread producer = new Thread(() => Producer());
    Thread consumer = new Thread(() => Consumer());
    producer.Start();
    consumer.Start();
    producer.Join();
    consumer.Join();
  }

  private void Producer()
  {
    for (int i = 0; i < 10; i++)
    {
      m_Queue.Enqueue(new Task());
    }
  }

  private void Consumer()
  {
    while (true)
    {
      Task task = m_Queue.Dequeue();
    }
  }
}
2 голосов
/ 27 апреля 2010

Я бы посоветовал вам взглянуть на пример для потребителя Джона Скита . Для получения дополнительной информации о производителе Consumer, проверьте Википедия

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