火和忘记(但不完全)

时间:2016-10-11 11:02:01

标签: c# events logging

跟进围绕Fire和Forget的许多问题提供的解决方案。我的情况是我想要触发被遗忘的事件。

我的解决方案基于Simplest way to do a fire and forget method in c# 4.0

这是我的测试代码。正如预期的那样,它永远无法保证它们将被处理的顺序。

    static void Main(string[] args)
    {
        Test(5);
        Console.WriteLine("5 sent");

        Test(2);
        Console.WriteLine("2 sent");

        Test(1);
        Console.WriteLine("1 sent");

        Test(4);
        Console.WriteLine("4 sent");

        Console.WriteLine("all sent");
        Console.ReadLine();

    }

    private static void Test(int messageNumber)
    {
        Action myMethod = () => {
            Task.Delay(messageNumber * 1000);
            Console.WriteLine(messageNumber);
        };
        Blindly.Run(myMethod);
    }

和我的输出

5 sent
2 sent
1 sent
4 sent
all sent
2
1
5
4

想象一下,您正在使用Fire和Forget进行日志记录。因此,您不想阻止调用代码,但希望按发生的顺序写入所有已记录的数据。

2 个答案:

答案 0 :(得分:1)

我会使用TPL数据流的ActionBlock(请参阅http://blog.stephencleary.com/2012/09/introduction-to-dataflow-part-2.html进行介绍)

这是一个NuGet包,所以看看它是否符合您的框架版本要求。

static void Main(string[] args)
{
    var a = new ActionBlock<int>(async (messageNumber) => 
    {
        await Task.Delay(messageNumber * 1000);
        Console.WriteLine(messageNumber);
    });

    a.Post(5);
    Console.WriteLine("5 sent");

    a.Post(2);
    Console.WriteLine("2 sent");

    a.Post(1);
    Console.WriteLine("1 sent");

    a.Post(4);
    Console.WriteLine("4 sent");

    Console.WriteLine("all sent");
    Console.ReadLine();
}

按照发布到ActionBlock的顺序,它将按照“即发即忘”的方式进行处理。

输出:

5 sent
2 sent
1 sent
4 sent
all sent
5
2
1
4

答案 1 :(得分:0)

我要做以下事情:

  • 为所有已记录的事件保留时间戳
  • 不要立即将事件写入日志(因为您异步运行它,您希望已经不那么担心了);而是保留记录消息的队列(集合,不一定是FIFO)
  • 每隔X毫秒,如果您有排队的日志消息,请排序并记录所有早于Y毫秒的(X和Y将取决于您的要求/设置)
  • 尝试在应用程序退出时刷新日志(确保即使它是例外情况也要执行此操作)