简体   繁体   中英

Fire and Forget (but not completely)

Following up with solutions provided in many questions around Fire and Forget. My scenario is that I want to run the Forgotten events in order they were triggered.

My solution is based on Simplest way to do a fire and forget method in c# 4.0

Here is my test code. And as expected it never guaranteed what order they will be processed.

    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);
    }

and my output

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

Imagine, you are using Fire and Forget for logging. So you don't want to block the calling code, but want to write all logged data in order they occurred.

I'd use the ActionBlock of the TPL Dataflow (See http://blog.stephencleary.com/2012/09/introduction-to-dataflow-part-2.html for an intro)

It's a NuGet package, so see if it fits your framework version requirements.

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();
}

It will be processed in a fire-and-forget manner in the order it has been posted to the ActionBlock .

Output:

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

I'd do the following:

  • keep a timestamp for all your logged events
  • don't write the events to log immediately (since you're running it asynchronously, you're hopefully already not that worried about it); instead keep a queue (a collection, not necessarily FIFO) of logged messages
  • every X milliseconds, if you have queued log messages, sort and log all the ones that are older than Y milliseconds (X and Y will depend on your requirements/setup)
  • attempt to flush the log whenever the application exits (make sure you're doing it even if it's an exception)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM