1

I have written a method to implement TPL ActionBlock, which will do a function to find the XPath of the element I am Posting to the block. I am sending the element from a real-time application (whenever the user finds an element Post it to the block). Now, I want to check the block is completed or not when I call a save button from another class. The logic is if the ActionBlok is completed when we click the save button element will save with some save logic, otherwise show a message box not yet ready. For the first time, this idea is working, but from the second element onwards the Actionblock is not accepting any. I am using block.Complete() and block.Completion.Wait() for the save check. Now I can show I am calling the code/logic.

  1. Once create an element, post it ActionBlock
    Class1
......
jobQ.Enqueue(familarizedElement);
......
  1. Inside the ActionBlock
    Class2
public class TPLCommonDataFlow
{
    private ActionBlock<Element> _jobs;
    public static bool TPLFlowStatus = false;
    public static string JobStatus = string.Empty;
    public TPLCommonDataFlow()
    {
        var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions()
        {
            MaxDegreeOfParallelism = 2,
        };

        _jobs = new ActionBlock<Element>((job) =>
        {
            Thread.Sleep(5);
            File.WriteAllText("C:\\Temp\\A.txt", "Started" + _jobs.InputCount.ToString());
            JobStatus = "started";
            Familiarization.FindAndUpdateXPath(job);
            File.WriteAllText("C:\\Temp\\A.txt", "Finished");
        }, executionDataflowBlockOptions);
        _jobs.Complete();


        //Wait for all messages to propagate through the network
        _jobs.Completion.Wait();

        //Checking all jobs are completed or not, if completed changing the boo, value.
        if (_jobs.InputCount == 0)
        {
            TPLFlowStatus = true;
            JobStatus = "stoped";
        }
    }
}
  1. For the save I am checking the TPLFlowStatus boolean
    Class3
if (class2.TPLFlowStatus == true)
{
    //Save Logic
}
else
{
    //Message Box showing Not Ready
}

Now what I want is to check each time the job is completed or not for each element in the save logic. If the block having two elements in Queue and one is finished, then the MessageBox needs to popup once the save button pressed. If all completed in the block, then need to go to the save logic.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
  • Welcome to Stack Overflow. Please take the [tour] to learn how Stack Overflow works and read [ask] on how to improve the quality of your question. Then [edit] your question to include the source code you have as a [mcve], which can be compiled and tested by others. – Progman May 01 '20 at 08:04
  • It seems that you never [`Post`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.dataflow.actionblock-1.post) anything to the `_jobs` block. Other than that it's not clear what you are trying to achieve. I noticed that the `TPLFlowStatus` and `JobStatus` properties are `static`, which doesn't make much sense. Also instead of logging with `File.WriteAllText`, I would suggest to switch to a [proper logging framework](https://stackoverflow.com/questions/1260157/whats-the-most-widely-used-logging-framework-in-c). – Theodor Zoulias May 01 '20 at 18:36

1 Answers1

1

The issue your seeing is that when a block is completed it will no longer accept new messages, you've told the block your done sending messages. To start sending a new batch of messages you can either keep the block alive by not calling complete and tracking the batch completion another way or you can just reset the block. A simple worker like this might be what you're looking for:

public class DataflowWorker
{
    private ActionBlock<string> _jobs;

    private void BuildJobsHandler()
    {
        _jobs = new ActionBlock<string>(x => Console.WriteLine(x) /*Do your work in the action block*/);
    }

    public async Task Enque(string element)
    {
        await _jobs.SendAsync(element);
    }

    public async Task CompleteJobsAndSave()
    {
        _jobs.Complete();
        await _jobs.Completion;
        //Save data when complete
        BuildJobsHandler();
    }
}
JSteward
  • 6,833
  • 2
  • 21
  • 30