Потокозащищённый LinkedList - C#

Узнай цену своей работы

Формулировка задачи:

Есть консольное приложение, работающее со списком LinkedList, реализованы функции добавления/удаления/изменения узлов. По заданию оно должно быть потокозащищённым и, следовательно, должна быть какая-то демонстрация - несколько потоков должны попытаться изменить список одновременно, но в итоге выполнить всё культурно по очереди. Затруднения возникают, с тем чтобы в несколько потоков выполнить команды типа
userList.AddFirst(data)
, например. Судя по мануалам, нужно создавать новый класс, уже он должен обращаться к методам из класса LinkedList, но так не выйдет, поскольку userList создаётся в Main(). Несколько идей было, вроде из Main передавать параметры в методы, там уже создавать список, вызывать все эти методы и прочее, но слишком сложно выходит, мне кажется. Надеюсь на любые советы по теме, код полностью приложу ниже (писал на основе коротенького примера со StackOverflow, половина кода - консольное меню):
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++)

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

13   голосов , оценка 3.846 из 5