Yahya
Yahya

Reputation: 3444

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.

Upvotes: 1

Views: 261

Answers (2)

Peter Bons
Peter Bons

Reputation: 29720

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

Upvotes: 1

decPL
decPL

Reputation: 5402

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)

Upvotes: 0

Related Questions