Search code examples
c#timerparallel.foreach

How can I access a variable set in Parallel ForEach outside the loop in C#?


RunQuestion is a method that uses a Parallel.ForEach loop to append the characters read to a StringBuilder variable (builder). The parallel loop is wrapped in a timer that fires every 10 seconds so that I can look at the content of the builder variable to find out how much of the data has been processed. The issue is the builder passed to DisplayOutput is always blank whenever the timer triggers. I am looking for a way to get the parallel for loop to update the builder object passed to DisplayOutput.

    public Task RunQuestion(ICharacterReader[] readers, IOutputResult output)
    {
        var wordsFrequency = new Dictionary<string, int>();
        var builder = new StringBuilder();
        var objLock = new object();

        try
        {
            var reportPeriod = TimeSpan.FromSeconds(10);
            using (new Timer(_ => DisplayOutput(builder), null, reportPeriod, reportPeriod))
            {
                Parallel.ForEach(readers, reader =>
                {
                    var stream = ReadStream(reader);
                    lock (objLock)
                        {
                            builder.Append(stream);
                        }
                });
            }

            wordsFrequency = GetWordsFrequency(builder);
        }
        catch (Exception ex)
        {
            throw;
        }

        return Task.FromResult(0);
    }

    private void DisplayOutput(StringBuilder builder)
    {
        foreach (var item in GetWordsFrequency(builder))
        {
            Debug.WriteLine($"{item.Key} - {item.Key}");
        }
    }

Solution

  • You'll have to create a different thread apart from the parallel.foreach that moniters the StringBuilder and reports status.