Многопоточная реализация с несколькими потребителями - PullRequest
3 голосов
/ 01 марта 2012

Я хотел бы реализовать загрузку нескольких файлов с шаблоном одного производителя и нескольких потребителей.

Что у меня есть: - Код, который находит новые ссылки для загрузки в цикле - Когда новая ссылка найдена- она ​​вызывает функцию загрузки - Функция загрузки принимает путь к исходному и конечному файлам и загружает файл.

Что я хочу сделать - я хочу загрузить X файлов одновременно (я не знаю общего количества файлов).) - В любой момент я должен иметь возможность загружать X-файлы одновременно - как только 1 из X-файлов завершит загрузку - вызывающая функция должна иметь возможность сразу добавить новую загрузку - которая, в свою очередь, загружает сразу

  • Итак, у меня есть функция производителя, которая продолжает добавлять новые загрузки в очередь (в любое время максимум X загрузок)
  • Несколько X потоков, которые потребляют загрузки и начинают загрузку по отдельности.Как только он завершит загрузку - продюсер должен будет добавить новую загрузку - что породит новую ветку.

ПРИМЕР будет очень признателен

Ответы [ 4 ]

5 голосов
/ 01 марта 2012

Для этой задачи P / C все, что вам нужно, это BlockingCollection<T>.

//shared and thread-safe
static BlockingCollection<string> queue = new BlockingCollection<string>(100);

// Producer
queue.Add(fileName);  // will block when full

// Consumer
if (queue.TryTake(out fileName, timeOut))  // waits when empty
  ...

Вы можете немного подстроить его с помощью тайм-аутов и токенов отмены.

2 голосов
/ 01 марта 2012

Класс ReaderWriterLockSlim предназначен для этого.

Кроме того, проверьте этот блестящий веб-сайт о потоках:

http://www.albahari.com/threading/part4.aspx#_Reader_Writer_Locks

Пример взят с сайта выше.

class SlimDemo
{
  static ReaderWriterLockSlim _rw = new ReaderWriterLockSlim();
  static List<int> _items = new List<int>();
  static Random _rand = new Random();

  static void Main()
  {
    new Thread (Read).Start();
    new Thread (Read).Start();
    new Thread (Read).Start();

    new Thread (Write).Start ("A");
    new Thread (Write).Start ("B");
  }

  static void Read()
  {
    while (true)
    {
      _rw.EnterReadLock();
      foreach (int i in _items) Thread.Sleep (10);
      _rw.ExitReadLock();
    }
  }

  static void Write (object threadID)
  {
    while (true)
    {
      int newNumber = GetRandNum (100);
      _rw.EnterWriteLock();
      _items.Add (newNumber);
      _rw.ExitWriteLock();
      Console.WriteLine ("Thread " + threadID + " added " + newNumber);
      Thread.Sleep (100);
    }
  }

  static int GetRandNum (int max) { lock (_rand) return _rand.Next(max); }
}
1 голос
/ 01 марта 2012

Используйте коллекцию Concurrent для связи между боссом и его рабочей командой.
Либо ConcurrentQueue (если вы заботитесь о заказе), либо ConcurrentBag.
Босс добавляет к ConcurrentQueue (метод Add), а команда берет из очереди (метод Take). Дайте мне знать, если вам нужен код.

0 голосов
/ 01 марта 2012

Я бы предложил заглянуть в Task Parallel Library . Это очень аккуратно оборачивает вызовы метода и управляет вашими несколькими потоками.

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