Странно работает подписка на события

Рейтинг: 0Ответов: 1Опубликовано: 22.05.2023

Мне нужно создать модель магазина. Есть покупатели, которые пробивают и оплачивают товары N секунд. А есть несколько касс, которые должны одновременно обслуживать всех покупателей раз в секунду. То есть каждую секунду время оплаты у покупателя уменьшается на 1, пока не станет 0 и он уйдёт.

Я написал маленький класс, который раз в секунду вызывает событие OneSecondPassed, на которое я планирую подписываться кассами.

class ShopTimer
{
    private System.Timers.Timer _timer = new System.Timers.Timer(1000);
    public event Action OneSecondPassed;

    public ShopTimer()
    {
        _timer.Elapsed += OnOneSecondPassed;
    }

    public void Start()
    {
        _timer.Start();
    }

    public void Stop()
    {
        _timer.Stop();
    }

    private void OnOneSecondPassed(object? o, System.Timers.ElapsedEventArgs e)
    {
        OneSecondPassed();
    }
}

В мейне всё прекрасно работает

class Program
{
    static void Main()
    {
        ShopTimer timer = new ShopTimer();
        timer.OneSecondPassed += test;
        timer.Start();

        while (true) { }
    }

    static void test()
    {
        Console.WriteLine(1);
    }
}

Но если я пытаюсь подписаться методом из класса Checkout (касса), то C# обязывает меня возвращать Action, что странно, ведь он возвращает его в никуда. Более того, методы Work() вызываются только один раз. То есть подписка работает, но таймер как-будто не идёт

class Shop
{
    private ShopTimer _timer = new ShopTimer();
    private Checkout[] _checkouts;

    public Shop(int amountOfCheckouts)
    {
        _checkouts = new Checkout[amountOfCheckouts];

        for (int i = 0; i < amountOfCheckouts; i++)
        {
            _checkouts[i] = new Checkout();
            _timer.OneSecondPassed += _checkouts[i].Work();
        }
    }
}

class Checkout
{
    // Не даёт написать void
    public Action Work()
    {
        Console.WriteLine("i am working");
        return null;  //Нужно хоть что-то вернуть, чтобы дал скомпилироваться
    }
}

Собственно, это так странно работает?

*Я убрал все проверки, чтобы легче читалось. Не обращайте внимание на небезопасный код

Ответы

▲ 1Принят

Перемудрили

public void Work()
{
    Console.WriteLine("i am working");
}
_timer.OneSecondPassed += _checkouts[i].Work; // без скобок

Кстати, не делайте вызов события (делегата) так

OneSecondPassed();

Безопаснее вот так:

OneSecondPassed?.Invoke();

Еще не делайте чтобы заморозить консоль так

while (true) { }

Делайте так

Console.ReadKey(); // ждёт нажатия любой клавиши