Страница 474 из 502
<b> Console.WriteLine("Потребляется символ " + ch);</b>
<b> }</b>
<b> }</b>
<b> static void Main() {</b>
<b> // Использовать блокирующую коллекцию,</b>
<b> // ограниченную 4 элементами,</b>
<b> bc = new BlockingCollection<char>(4);</b>
<b> // Создать задачи поставщика и потребителя.</b>
<b> Task Prod = new Task(Producer);</b>
<b> Task Con = new Task(Consumer);</b>
<b> // Запустить задачи.</b>
<b> Con.Start();</b>
<b> Prod.Start();</b>
<b> // Ожидать завершения обеих задач,</b>
<b> try {</b>
<b> Task.WaitAll(Con, Prod);</b>
<b> } catch(AggregateException exc) {</b>
<b> Console.WriteLine (exc);</b>
<b> } finally {</b>
<b> Con.Dispose();</b>
<b> Prod.Dispose();</b>
<b> bc.Dispose();</b>
<b> }</b>
<b> }</b>
<b>}</b>
Этот вариант программы дает такой же результат, как и предыдущий. Главное его отличие заключается в том, что теперь метод Producer() может производить и поставлять сколько угодно элементов. С этой целью он просто вызывает метод CompleteAdding(), когда завершает создание элементов. А метод Consumer() лишь "потребляет" произведенные элементы до тех пор, пока свойство IsCompleted не примет логическое значение true.
Несмотря на специфический до некоторой степени характер параллельных коллекций, предназначенных в основном для параллельного программирования, у них, тем не менее, имеется немало общего с обычными, непараллельными коллекциями, описанными в предыдущих разделах. Если же вам приходится работать в среде параллельного программирования, то для организации одновременного доступа к данным из нескольких потоков вам, скорее всего, придется воспользоваться параллельными коллекциями.
Сохранение объектов, определяемых пользователем классов, в коллекции
Ради простоты приведенных выше примеров в коллекции, как правило, сохранялись объекты встроенных типов, в том числе int, string и char. Но ведь в коллекции можно хранить не только объекты встроенных типов. Достоинство коллекций в том и состоит, что в них допускается хранить объекты любого типа, включая объекты определяемых пользователем классов.
Рассмотрим сначала простой пример применения класса необобщенной коллекции ArrayList для хранения информации о товарных запасах. В этом классе инкапсулируется класс Inventory.
<b>// Простой пример коллекции товарных запасов.</b>
<b>using System;</b>
<b>using System.Collections;</b>
<b>class Inventory {</b>
<b> string name;</b>
<b> double cost;</b>
<b> int onhand;</b>
<b> public Inventory(string n, double c, int h) {</b>
<b> name = n;</b>
<b> cost = c;</b>
<b> onhand = h;</b>
<b> }</b>
<b> public override string ToString() {</b>
<b> return</b>
<b> String.Format("{0,-10}Стоимость: {1,6:C} Наличие: {2}",</b>
<b> name, cost, onhand);</b>
<b> }</b>
<b>}</b>
<b>class InventoryList {</b>
<b> static void Main() {</b>
<b> ArrayList inv = new ArrayList();</b>
<b> // Добавить элементы в список.</b>
<b> inv.Add(new Inventory("Кусачки", 5.95, 3));</b>
<b> inv.Add(new Inventory("Отвертки", 8.29, 2));</b>
<b> inv.Add(new Inventory("Молотки", 3.50, 4));</b>
<b> inv.Add(new Inventory("Дрели", 19.88, 8));</b>
<b> Console.WriteLine("Перечень товарных запасов:");</b>
<b> foreach(Inventory i in inv) {</b>
<b> Console.WriteLine(" " + i);</b>
<b> }</b>
<b> }</b>
<b>}</b>
При выполнении программы из данного примера получается следующий результат.
<b>Перечень товарных запасов:</b>
<b> Кусачки Стоимость: $5,95 Наличие: 3</b>