2

I am trying to use action block to execute some tasks. My question is when the CreateActionBlock() method finishes, the ActionBlock is still processing the data. Since the method is returned and I do not have a way to call actionBlock.Complete(). Will it cause any problems if I run this CreateActionBlock() thousand times? Will there be thousand of actionBlocks forever in the memory or they will be GC'ed after the 5 inputs processed?

private static async Task Dequeue(string content)
{
    Console.WriteLine("The string is " + content);
    await Task.Delay(10000);
}

public static void CreateActionBlock()
{
    var actionBlock = new ActionBlock<string>(
        (e) => Dequeue(e),
        new ExecutionDataflowBlockOptions()
        {
            BoundedCapacity = 5,
            MaxDegreeOfParallelism = 1
        });

    for (int i = 0; i < 5; i++)
    {
        actionBlock.Post(i.ToString());
    }
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
user1722361
  • 377
  • 1
  • 4
  • 14
  • Somewhat related: [Does linking keep the linked block alive?](https://stackoverflow.com/questions/49435787/does-linking-keep-the-linked-block-alive) – Theodor Zoulias Feb 18 '21 at 12:33
  • 1
    The answer to "will it cause any problems" is *probably* yes. The action block will work fine, and the GC will work fine, but your program will not know when it is safe to exit. So from a very broad perspective, fire-and-forget means you're ok with losing work. Which most programs are not ok with. But if you're OK with losing work when your program exits, then this will work. – Stephen Cleary Feb 18 '21 at 15:10

1 Answers1

2

A dataflow block is eligible for garbage collection as soon as its input queue has been emptied, and it is currently idle. Below is an example that demonstrates this behavior:

var weakReference = InnerMethod();
for (int i = 1; i <= 10; i++)
{
    Thread.Sleep(100);
    GC.Collect();
    Console.WriteLine($"IsAlive: {weakReference.IsAlive}");
}

WeakReference InnerMethod()
{
    var block = new ActionBlock<int>(n =>
    {
        Thread.Sleep(200);
        Console.WriteLine($"Processed: {n}");
    });
    block.Post(1); block.Post(2); block.Post(3);
    return new WeakReference(block);
}

Output:

IsAlive: True
Processed: 1
IsAlive: True
IsAlive: True
Processed: 2
IsAlive: True
IsAlive: True
Processed: 3
IsAlive: False
IsAlive: False
IsAlive: False
IsAlive: False
IsAlive: False

(Try it on Fiddle)

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104