Потокозащищённый LinkedList - C#
Формулировка задачи:
Есть консольное приложение, работающее со списком LinkedList, реализованы функции добавления/удаления/изменения узлов. По заданию оно должно быть потокозащищённым и, следовательно, должна быть какая-то демонстрация - несколько потоков должны попытаться изменить список одновременно, но в итоге выполнить всё культурно по очереди. Затруднения возникают, с тем чтобы в несколько потоков выполнить команды типа , например. Судя по мануалам, нужно создавать новый класс, уже он должен обращаться к методам из класса LinkedList, но так не выйдет, поскольку userList создаётся в Main(). Несколько идей было, вроде из Main передавать параметры в методы, там уже создавать список, вызывать все эти методы и прочее, но слишком сложно выходит, мне кажется. Надеюсь на любые советы по теме, код полностью приложу ниже (писал на основе коротенького примера со StackOverflow, половина кода - консольное меню):
userList.AddFirst(data)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace theLastSharpian { public class Node { public Node next; public Object data; } public class LinkedList { private Node head; public void printAllNodes() { Console.WriteLine("List of nodes:"); if (head == null) Console.WriteLine("| List empty."); else { Console.WriteLine("| № next data"); Console.WriteLine("|--------------------------"); Node current = head; int i = 1; while (current != null) { string tempword = "link"; if (current.next == null) tempword = "null"; Console.WriteLine("| {0}. {1} {2};", i++, tempword, current.data); current = current.next; } } } public void AddFirst(Object data) { if (head == null) { head = new Node(); head.data = data; head.next = null; } else { Node tmp = new Node(); Node toAdd = new Node(); toAdd.data = data; toAdd.next = head; head = toAdd; tmp = head.next; } } public void AddLast(Object data) { if (head == null) { head = new Node(); head.data = data; head.next = null; } else { Node toAdd = new Node(); toAdd.data = data; Node current = head; while (current.next != null) current = current.next; current.next = toAdd; } } public void AddAfter(int x, Object data) { if (head == null) Console.WriteLine("List empty"); else { Node toAdd = new Node(); toAdd.data = data; Node temp = head; Node current = head; for (int i = 0; i < x; i++) { temp = current; current = current.next; } temp.next = toAdd; toAdd.next = current; } } public void ChangeData(int x, Object data) { if (head == null) Console.WriteLine("List empty"); else { Node current = head; for (int i = 0; i < x-1; i++) current = current.next; current.data = data; } } public void DeleteFirst() { if (head == null) Console.WriteLine("List already empty"); else { Node current = head; head = current.next; current.next = null; current.data = null; Console.WriteLine("Item deleted"); if (head == null) Console.WriteLine("List now empty"); } } public void DeleteLast() { if (head == null) Console.WriteLine("List already empty"); else { Node temp = head; Node current = head; while (current.next != null) { temp = current; current = current.next; } current.next = null; current.data = null; temp.next = null; Console.WriteLine("Item deleted"); if (temp.data == null) { head = null; Console.WriteLine("List now empty"); } } } public void DeleteAfter(int x) { if (head == null) Console.WriteLine("List empty"); else { Node temp = head; Node current = head; for (int i = 0; i < x; i++) { temp = current; current = current.next; } if (current == null) Console.WriteLine("Error. There is nothing after last node. Maybe DeleteLast fits your needs?"); else { temp.next = current.next; current.next = null; current.data = null; Console.WriteLine("Item deleted"); if (temp.data == null) { head = null; Console.WriteLine("List now empty"); } } } } } /// <summary> /// можно сделать вывод покрасивее, менее захламленным /// если ввести некорректное N получится нехорошо. можно вообще добавить отдельный метод просто для ввода корректного N /// </summary> class Program { static void Main() { Console.Title = "Super non-cool app for ITS specialists - linked list with such thread safety wow"; string key = "800"; int N, kol=0, kol2; LinkedList userList = new LinkedList(); do { Console.WriteLine("------------------------------------------------------------\n Any key to proceed to menu"); Console.ReadKey(); Console.Clear(); Console.WriteLine("0. Exit program\n-userList [{0} items] manual control:\nf. Fill userList\n1. Print all nodes\n2. Change data in node", kol); Console.WriteLine("3. Add node(s) with AddLast\n4. Add node(s) with AddFirst\n5. Add node with AddAfter"); Console.WriteLine("6. Delete node(s) with DeleteLast\n7. Delete node(s) with DeleteFirst\n8. Delete node with DeleteAfter\n9. Delete all nodes"); Console.WriteLine("-non-userList commands:\nt. non-usable thread info"); key = Console.ReadLine(); string data; switch (key) { case "1": Console.WriteLine("------------------------------------------------------------"); userList.printAllNodes(); break; case "2": Console.WriteLine("------------------------------------------------------------"); Console.WriteLine("Select node for ChangeData:"); userList.printAllNodes(); if (kol > 0) { N = Convert.ToInt32(Console.ReadLine()); Console.Write("Enter data: "); data = Console.ReadLine(); userList.ChangeData(N, data); } else Console.WriteLine("Can not process empty list"); break; case "3": Console.WriteLine("------------------------------------------------------------"); Console.Write("AddLast. How much nodes? "); N = Convert.ToInt32(Console.ReadLine()); kol2 = kol + N; while (kol != kol2) { Console.Write("{0} = ", kol + 1); data = Console.ReadLine(); userList.AddLast(data); kol++; } Console.WriteLine("Now there is {0} items", kol); break; case "4": Console.WriteLine("------------------------------------------------------------"); Console.Write("AddFirst. How much nodes? "); N = Convert.ToInt32(Console.ReadLine()); kol2 = kol + N; int i = N; while (kol != kol2) { Console.Write("{0} = ", i); data = Console.ReadLine(); userList.AddFirst(data); kol++; i--; } Console.WriteLine("Now there is {0} items", kol); break; case "5": Console.WriteLine("------------------------------------------------------------"); Console.WriteLine("Select node for AddAfter:"); userList.printAllNodes(); N = Convert.ToInt32(Console.ReadLine()); Console.Write("Enter data: "); data = Console.ReadLine(); kol2 = kol + 1; while (kol != kol2) { userList.AddAfter(N, data); kol++; } Console.WriteLine("Now there is {0} items", kol); break; case "6": Console.WriteLine("------------------------------------------------------------"); Console.Write("DeleteLast. How much nodes? "); N = Convert.ToInt32(Console.ReadLine()); kol2 = kol - N; while (kol != kol2) { userList.DeleteLast(); kol--; } Console.WriteLine("Now there is {0} items", kol); break; case "7": Console.WriteLine("------------------------------------------------------------"); Console.Write("DeleteFirst. How much nodes? "); N = Convert.ToInt32(Console.ReadLine()); kol2 = kol - N; while (kol != kol2) { userList.DeleteFirst(); kol--; } Console.WriteLine("Now there is {0} items", kol); break; case "8": Console.WriteLine("------------------------------------------------------------\n"); Console.WriteLine("Select node for DeleteAfter:"); userList.printAllNodes(); N = Convert.ToInt32(Console.ReadLine()); kol2 = kol - 1; while (kol != kol2) { userList.DeleteAfter(N); kol--; } Console.WriteLine("Now there is {0} items", kol); break; case "9": Console.WriteLine("------------------------------------------------------------"); Console.WriteLine("Deleting all nodes"); while (kol != 0) { userList.DeleteLast(); kol--; } Console.WriteLine("Now there is {0} items", kol); break; case "f": userList.AddLast("first"); userList.AddLast("second"); userList.AddLast("third"); userList.AddLast("fourth"); userList.AddLast("fifth"); userList.AddLast("sixth"); userList.AddLast("last"); Console.WriteLine("7 items added"); kol = kol + 7; Console.WriteLine("Now there is {0} items", kol); break; case "t": Thread mainThread = Thread.CurrentThread; mainThread.Name = "Main Thread"; Console.WriteLine("Имя домена приложения: {0}\nID контекста: {1}\nИмя потока: {2}\nЗапущен ли поток? {3}\nПриоритет потока: {4}\nСостояние потока: {5}", Thread.GetDomain().FriendlyName, Thread.CurrentContext.ContextID, mainThread.Name, mainThread.IsAlive, mainThread.Priority, mainThread.ThreadState); break; case "0": Console.WriteLine("Goodbye"); break; default: Console.WriteLine("No correct key"); break; } } while (key != "0"); Console.ReadLine(); } } }
Решение задачи: «Потокозащищённый LinkedList»
textual
Листинг программы
lock (_locker) for (int i = 0; i < 5; i++)
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д