C# как создать очередь действий, где действия имеют разные параметры - PullRequest
1 голос
/ 13 апреля 2020

Мой вопрос: как запустить различные функции с параметрами в существующем потоке? Мне известно, что я должен сформировать очередь из этого потока от @ user2864740 :

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace DogPark
{
    internal class DogPark
    {

        private readonly string _parkName;
        private readonly Thread _thread;
        private readonly ConcurrentQueue<Action> _actions = new ConcurrentQueue<Action>();
        private volatile bool _isOpen;

        public DogPark(string parkName)
        {
            _parkName = parkName;
            _isOpen = true;
            _thread = new Thread(OpenPark);
            _thread.Name = parkName;
            _thread.Start();
        }

        // Runs in "target" thread
        private void OpenPark(object obj)
        {
            while (true)
            {
                Action action;
                if (_actions.TryDequeue(out action))
                {
                    Program.WriteLine("Something is happening at {0}!", _parkName);
                    try
                    {
                        action();
                    }
                    catch (Exception ex)
                    {
                        Program.WriteLine("Bad dog did {0}!", ex.Message);
                    }
                }
                else
                {
                    // Nothing left!
                    if (!_isOpen && _actions.IsEmpty)
                    {
                        return;
                    }
                }

                Thread.Sleep(0); // Don't toaster CPU
            }
        }

        // Called from external thread
        public void DoItInThePark(Action action)
        {
            if (_isOpen)
            {
                _actions.Enqueue(action);
            }
        }

        // Called from external thread
        public void ClosePark()
        {
            _isOpen = false;
            Program.WriteLine("{0} is closing for the day!", _parkName);
            // Block until queue empty.
            while (!_actions.IsEmpty)
            {
                Program.WriteLine("Waiting for the dogs to finish at {0}, {1} actions left!", _parkName, _actions.Count);

                Thread.Sleep(0); // Don't toaster CPU
            }
            Program.WriteLine("{0} is closed!", _parkName);
        }

    }

    internal class Dog
    {

        private readonly string _name;

        public Dog(string name)
        {
            _name = name;
        }

        public void Run()
        {
            Program.WriteLine("{0} is running at {1}!", _name, Thread.CurrentThread.Name);
        }

        public void Bark()
        {
            Program.WriteLine("{0} is barking at {1}!", _name, Thread.CurrentThread.Name);
        }

    }

    internal class Program
    {
        // "Thread Safe WriteLine"
        public static void WriteLine(params string[] arguments)
        {
            lock (Console.Out)
            {
                Console.Out.WriteLine(arguments);
            }
        }

        private static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "Home";

            var yorkshire = new DogPark("Yorkshire");
            var thunderpass = new DogPark("Thunder Pass");

            var bill = new Dog("Bill the Terrier");
            var rosemary = new Dog("Rosie");

            bill.Run();

            yorkshire.DoItInThePark(rosemary.Run);
            yorkshire.DoItInThePark(rosemary.Bark);

            thunderpass.DoItInThePark(bill.Bark);

            yorkshire.DoItInThePark(rosemary.Run);

            thunderpass.ClosePark();
            yorkshire.ClosePark();
        }

    }
}

, но в этом примере используются только функции, которые принимают 0 параметров. Какой подход был бы, если бы "Dog.Run" и "Dog.Bark" принимали разные (длина) параметры?

4 пример:

public void Bark(int value)
{
   //do something
}
public void Run (string speed, string direction)
{
   //do something
}

лучшая вещь, которую я придумал так far использует выражение lamba, но я бы хотел иметь как можно больше разных точек зрения для решения этой проблемы, чтобы иметь возможность найти наиболее элегантное решение.

public void SendRun(string speed, string direction)
{
    this.DoItInThePark(new Action(() => Run(speed,direction)));
}
public void Run(string speed, string direction)
{
    //do something
}

если у вас другой подход к той же проблеме, пожалуйста, предложите.

В моем проекте Dog и Park даже не должны быть отдельными классами, но все действия могут быть выполнены в пределах одного класса (но я думаю, что это не имеет большого значения для обсуждения)

...