我如何创建事件代表队列,以便稍后再提出?

时间:2019-04-12 15:19:31

标签: c# list events delegates

是否可以将事件(或委托)添加到列表中,以便稍后可以提高偶数;就像能够缓存raise事件以将其推迟到以后再使用(例如缓冲事件)。

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

namespace DelegateQueue {
    class Program {

        delegate void SomeTimeLaterDelegate(int myValue);
        static event SomeTimeLaterDelegate SomeTimeLater;
        static void Main(string[] args) {
            SomeTimeLater += new SomeTimeLaterDelegate(AnswerAnotherDay);
            SomeTimeLater += new SomeTimeLaterDelegate(ItIsPossible);
            SomeTimeLater += new SomeTimeLaterDelegate(HenceTheNeed);

            List<Delegate> delegates = new List<Delegate>();

            SomeTimeLater.Invoke(100); // <== I need to trap this call in a list that I can invoke later.
            ///both the function call and the value that I'm passing.
            ///the problem is that there are lots of different events and they must be invoked in the order
            ///that they occoured (i.e. no skipping in the buffer)

        }

        static void AnswerAnotherDay(int howManyDays) {
            Console.WriteLine($"I did this {howManyDays}, later. Hurray for procrastination!");
        }

        static void ItIsPossible(int numberOfPossibilities) {
        ///that there is in invocation list for the event
        ///which means that I would have to call each function in that list and pass them the value

        }

        static void HenceTheNeed(int needs) {
        ///hence the need to queue the Invocation of the event to a later point
        }
    }
}

该事件可能有多个订阅者,因此需要从发布者方面而不是订阅者方面进行缓冲。

2 个答案:

答案 0 :(得分:1)

这是您所描述内容的字面示例:

class Program
{
    delegate void SomeTimeLaterDelegate(int myValue);
    delegate void SayHelloDelegate(string name);

    static event SomeTimeLaterDelegate SomeTimeLaterEvent;
    static event SayHelloDelegate SayHelloLaterEvent;
    static void Main(string[] args)
    {
        SomeTimeLaterEvent += new SomeTimeLaterDelegate(AnswerAnotherDay);
        SayHelloLaterEvent += new SayHelloDelegate(SayHello);

        var eventsToRaise = new Queue<Action>();
        eventsToRaise.Enqueue(() => SomeTimeLaterEvent.Invoke(100));
        eventsToRaise.Enqueue(() => SayHelloLaterEvent.Invoke("Bob"));
        eventsToRaise.Enqueue(() => SomeTimeLaterEvent.Invoke(200));
        eventsToRaise.Enqueue(() => SayHelloLaterEvent.Invoke("John"));

        while (eventsToRaise.Any())
        {
            var eventToRaise = eventsToRaise.Dequeue();
            eventToRaise();
            //or eventToRaise.Invoke();
        }

        Console.ReadLine();
    }

    static void AnswerAnotherDay(int howManyDays)
    {
        Console.WriteLine($"I did this {howManyDays}, later. Hurray for procrastination!");
    }

    static void SayHello(string name)
    {
        Console.WriteLine($"Hello, {name}");
    }
}

这是Queue<Delegate>,而不是Queue<Action>Action表示调用方法而不传递任何参数或接收返回值。

这听起来违反直觉,因为您正在传递参数。但是您没有将参数传递给动作。您正在从动作主体内部传递参数。

这可能会也可能不会有帮助:

当我们宣布

Action someAction = () => AnswerAnotherDay(5);

这就像声明一个如下所示的方法:

void MyMethod()
{
    AnswerAnotherDay(5);
}

该方法调用另一个方法并传递一个参数。但是MyMethod本身不接受任何参数。当我们像这样声明一个内联方法时,它没有名称,因此也称为 anonymous 方法。

我们还可以声明一个带有参数的动作,像这样:

Action<string> action = (s) => SayHelloLater(s);
action("Bob");

我之所以演示不带参数的Action是因为您说队列可能需要包含具有不同参数的不同类型的事件。

如果我要使用不同的参数一遍又一遍地调用相同的方法,则将参数放入队列可能更有意义。然后,每次我们从队列中取出参数时,都可以使用下一个参数引发事件。

这里可能是一种简化:也许您正在考虑需要引发事件的情况,但是在此示例中,我们可以在没有事件的情况下做完全相同的事情,并且这有点简单。

我们可以只创建调用方法的操作,而不是定义委托和事件,将某些方法添加为事件处理程序,然后创建引发事件的操作。

class Program
{
    static void Main(string[] args)
    {
        var eventsToRaise = new Queue<Action>();
        eventsToRaise.Enqueue(() => AnswerAnotherDay(100));
        eventsToRaise.Enqueue(() => SayHello("Bob"));
        eventsToRaise.Enqueue(() => AnswerAnotherDay(200));
        eventsToRaise.Enqueue(() => SayHello("John"));

        while (eventsToRaise.Any())
        {
            var eventToRaise = eventsToRaise.Dequeue();
            eventToRaise();
            //or eventToRaise.Invoke();
        }

        Console.ReadLine();
    }

    static void AnswerAnotherDay(int howManyDays)
    {
        Console.WriteLine($"I did this {howManyDays}, later. Hurray for procrastination!");
    }

    static void SayHello(string name)
    {
        Console.WriteLine($"Hello, {name}");
    }
}

答案 1 :(得分:0)

这是我要面对的挑战:

delegate void SomeTimeLaterDelegate(int myValue);
static event SomeTimeLaterDelegate SomeTimeLater;

static Queue<int> SomeTimeLaterQueue = new Queue<int>(); // Here we store the event arguments

static async Task Main(string[] args)
{
    SomeTimeLater += new SomeTimeLaterDelegate(AnswerAnotherDay); // Subscribe to the event
    await Task.Delay(100);
    OnSomeTimeLaterDefered(10); // Raise an defered event
    await Task.Delay(100);
    OnSomeTimeLaterDefered(20); // Raise another defered event
    await Task.Delay(100);
    OnSomeTimeLaterDefered(30); // Raise a third defered event
    await Task.Delay(100);
    OnSomeTimeLaterFlush(); // Time to raise the queued events for real!
}

static void OnSomeTimeLaterDefered(int value)
{
    SomeTimeLaterQueue.Enqueue(value);
}
static void OnSomeTimeLaterFlush()
{
    while (SomeTimeLaterQueue.Count > 0)
    {
        SomeTimeLater?.Invoke(SomeTimeLaterQueue.Dequeue());
    }
}

static void AnswerAnotherDay(int howManyDays)
{
    Console.WriteLine($"I did this {howManyDays}, later. Hurray for procrastination!");
}

输出:

I did this 10, later. Hurray for procrastination!
I did this 20, later. Hurray for procrastination!
I did this 30, later. Hurray for procrastination!