Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Непонятно с async-await в C# - 2

03.09.21 19:22
Re: Непонятно с async-await в C# - 2
 
alex445 свой человек
в ответ AlexNek 03.09.21 17:01, Последний раз изменено 03.09.21 19:41 (alex445)

Что-то типа такого накидал на .NET 5. Одним потоком пишем в лист случайное число данных в определённых пределах, другим читаем каждый раз фиксированное число НОВЫХ данных, если их набралось достаточно, нажимая на "у". Сделал паузу при добавлении данных в 3 секунды специально, чтобы если слишком часто нажимать на "у" ничего не читалось. Правда, клавиатурный воод буферизуется, поэтому все нажатия "у" запоминаются, даже если данных на данный момент не достаточно, и потом автоматом вводятся - следовательно, выводятся и значения из данных, даже если "у" больше не нажималось. Как это отключить - пока не придумал. Да и не требуется особо.


Операция чтения data.Count атомарная, насколько я понимаю, поэтому её чтение всегда даст число данных на текущий момент, как бы в список данные ни добавлялись. Да это и не важно - Count не может уменьшаться, а значит, я никогда не выйду за пределы реального числа данных в списке, кроме случая переполнения.


В таком предельно упрощённом случае работы потоков со списком блокировки и синхронизации не делаю - они не нужны. Если, конечно, там внутри при добавлении данных и чтении методами AddRange и GetRange не происходит каких-то потокобезопасных переаллокаций, который повлияют на порядок чтения данных из списка - например, поменяют индексы значений в списке. Но, судя по всему, такой дичи там не происходит - нелогично было бы, что при добавлении данных список бы внутри как-то передвигал значения уже хранящихся элементов или двигал их в памяти так, что при чтении клиент попадал бы на другие элементы. Ну и судя по работе программы, таких кульбитов не происходит. Может, они происходят очень редко?


Просто, на мой взгляд, в МСДНе дана общая рекомендация - список и его публичные методы не потокобезопасны в общем случае. А я предельно упростил, так что хоть список и не потокобезопасен, но по моей логике работы с его данныеми с ними ничего произойти не может.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static List<int> data = new();

        static int dataReadSize = 5;
        static int currentIndexToRead = 0;

        static Random r = new();

        static bool doWork = true;

        static void Main(string[] args)
        {
            Thread writeThread = new(new ThreadStart(WriteData));
            writeThread.IsBackground = true;
            writeThread.Start();

            Thread readThread = new(new ThreadStart(ReadData));
            readThread.IsBackground = true;
            readThread.Start();

            // to prevent app to end immediately
            while (doWork)
                Thread.Sleep(100);
        }

        static void WriteData()
        {
            while (doWork)
            {
                data.AddRange(
                    Enumerable.Range(
                        0,
                        r.Next(3, 9)));

                Thread.Sleep(3000); // imitate pause
            }
        }


        static void ReadData()
        {
            Console.WriteLine("Press 'y' to continue or any another key to stop.");

            while (doWork)
            {
                int howMuchCanRead = data.Count - currentIndexToRead;
                bool canRead = howMuchCanRead >= dataReadSize;

                if (canRead)
                {
                    if (Console.ReadKey(true).Key != ConsoleKey.Y)
                        doWork = false;

                    var buffer = data.GetRange(currentIndexToRead, dataReadSize);
                    currentIndexToRead += dataReadSize;

                    Console.WriteLine(string.Join(',', buffer));
                }
            }
        }
    }
}
 

Перейти на