Click here to Skip to main content
15,887,214 members
Home / Discussions / C#
   

C#

 
AnswerRe: Multiple chart display in winforms devexpress Pin
Eddy Vluggen24-Apr-21 6:10
professionalEddy Vluggen24-Apr-21 6:10 
AnswerRe: Multiple chart display in winforms devexpress Pin
Gerry Schmitz27-Apr-21 11:03
mveGerry Schmitz27-Apr-21 11:03 
QuestionSeparating numbers joined by "," into an array Pin
Alex Dunlop23-Apr-21 5:50
Alex Dunlop23-Apr-21 5:50 
AnswerRe: Separating numbers joined by "," into an array Pin
Richard MacCutchan23-Apr-21 6:09
mveRichard MacCutchan23-Apr-21 6:09 
AnswerRe: Separating numbers joined by "," into an array Pin
Dave Kreskowiak23-Apr-21 6:12
mveDave Kreskowiak23-Apr-21 6:12 
GeneralRe: Separating numbers joined by "," into an array Pin
Alex Dunlop23-Apr-21 6:53
Alex Dunlop23-Apr-21 6:53 
AnswerRe: Separating numbers joined by "," into an array Pin
OriginalGriff23-Apr-21 8:26
mveOriginalGriff23-Apr-21 8:26 
QuestionSeeking a better understanding of .NET multithreading and the System.Threading.Tasks.Parallel methods Pin
pr1mem0ver23-Apr-21 1:36
pr1mem0ver23-Apr-21 1:36 
I have a project that needs the ability to modify dozens, hundreds, and potentially thousands of file modifications which are fairly intensive and affect associated resource files as well. To speed things up and maximize the ability to process multiple threads to take advantage of parallel processing I decided to use the System.Threads.Tasks.Parallel class to drive these file changes. There are a few things that I have learned and discovered along the way that I would like to better understand.

First, before I go any further, my project has a BIG need to track all changes in a log file that occur BEFORE they happen to minimize the risk of losing data when something goes wrong. That log file is then parsed for undo actions. This requires the chain of events to be tracked; and logging each change before it happens requires several sub-tasks that use .NET's await feature. A basic picture of the process used to change the files looks something like this:

C#
public class MainFileType
{
    internal async void DoSomeMajorChanges(RichTextboxBuilder builder, StreamWriter changeLog)
    {
        bool result;
        await Task.Run(new Action(() => changeLog.LogAction(this))).ConfigureAwait(false);
        await Task.Run(new Action(()=> result = coreFile.DoChanges())).ConfigureAwait(false);
        builder.Control.BeginInvoke(new Action() builder.NotifyUser("Some Change Occurred", Color.Red));
        foreach (ResourceFile file in this.AssociatedFiles)
        {
            await Task.Run(new Action(() => changeLog.LogAction(file))).ConfigureAwait(false);
            await Task.Run(new Action(() => result |= file.DoChanges())).ConfigureAwait(false);
            builder.Control.BeginInvoke(new Action() builder.NotifyUser("Some Change Occurred", Color.Blue));
        }
        return result;
    }
}

This code is called by a UI that is shown any time a single or multiple files are modified. The UI regularly reports to the user:

public class ChangeManagerUI : Form
{
    private bool processed;
    object task;
    StreamWriter parseableActionLog;

    private void OnFormShown(object sender, EventArgs e)
    {
        if (!processed)
        {
            processed = true;
            MainFileType file;
            RichTextboxBuilder builder = null;
            List<MainFileType> batch = task as List<MainFileType>;
            Refresh();
            if (batch != null)
            {
                RichTextboxBuilder.BeginConcurrentAppendProcess(this, batch.Count);
                ReportCaption = "Conversion Progress";
                progressBar.Visible = true;
                progressBar.Maximum = batch.Count;
                ConcurrentOutputManager.ConcurrentMode = true;

                Task.Run(() =>
                {
                    Parallel.For(0, batch.Count, i =>
                    {
                        file = batch[i];
                        builder = RichTextboxBuilder.BeginConcurrentAppend(i);
                        //builder.TextUpdated += Builder_TextUpdated;
                        file.DoSomeMajorChanges(builder, parseableActionLog)
                        RichTextboxBuilder.EndConcurrentAppend(i);
                    });
                });
                if (builder != null)
                {
                    builder.AppendNewLine();
                    builder.BeginColor(Color.Purple);
                    builder.AppendStyled("Batch Conversion Complete!", FontStyle.Bold);
                    builder.EndColor();
                }
                Finalize(false);
            }
            else
            {
                file = task as MainFileType;
                ReportTextBuilder = new RichTextboxBuilder(this);
                Finalize(file.DoSomeMajorChanges(mod, ReportTextBuilder).Result);
            }
        }
    }
}

The things that I have noticed that I would like to understand are as follows:

1. If I remove the Task.Run( (line 24) that encapsulates the Parallel.For statement the program/UI locks up (stops responding) even though I am using ConfigureWait(false) in the await commands... I know that using await in the UI thread can lead to this kind of issue but as I understand, Parallel methods use separate threads.

2. Sometimes Parallel.For seems to run the action for the same item repeatedly rather than go to the next item. Do I need to explicitly code the increment? Because of this, I switched to the Parallel.Foreach method and that works more consistently.

3. I had a problem in that the code AFTER the Task.Run => Parallel.For block was run before the parallel tasks completed (which led to my discovery of 1). I fixed it by using an atomic integer that was initialized to the number of tasks and calling a method that decreased that number inside the Parallel.For each statement that would only run a block of code if the number hit zero. However, I would still like to know why this occurred and if there is another .NET mechanism for achieving the goal executing code after parallel tasks are completed built in.
AnswerRe: Seeking a better understanding of .NET multithreading and the System.Threading.Tasks.Parallel methods Pin
Richard Deeming23-Apr-21 6:37
mveRichard Deeming23-Apr-21 6:37 
GeneralRe: Seeking a better understanding of .NET multithreading and the System.Threading.Tasks.Parallel methods Pin
pr1mem0ver24-Apr-21 4:09
pr1mem0ver24-Apr-21 4:09 
GeneralRe: Seeking a better understanding of .NET multithreading and the System.Threading.Tasks.Parallel methods Pin
Richard Deeming25-Apr-21 21:16
mveRichard Deeming25-Apr-21 21:16 
GeneralRe: Seeking a better understanding of .NET multithreading and the System.Threading.Tasks.Parallel methods Pin
pr1mem0ver24-Oct-21 11:49
pr1mem0ver24-Oct-21 11:49 
AnswerRe: Seeking a better understanding of .NET multithreading and the System.Threading.Tasks.Parallel methods Pin
Gerry Schmitz23-Apr-21 7:07
mveGerry Schmitz23-Apr-21 7:07 
QuestionIPC Implementation for sending an integer from C++ exe to C# exe Pin
LokeshVarman22-Apr-21 22:32
LokeshVarman22-Apr-21 22:32 
QuestionRe: IPC Implementation for sending an integer from C++ exe to C# exe Pin
Richard MacCutchan22-Apr-21 23:05
mveRichard MacCutchan22-Apr-21 23:05 
AnswerRe: IPC Implementation for sending an integer from C++ exe to C# exe Pin
Victor Nijegorodov22-Apr-21 23:11
Victor Nijegorodov22-Apr-21 23:11 
GeneralRe: IPC Implementation for sending an integer from C++ exe to C# exe Pin
LokeshVarman23-Apr-21 0:06
LokeshVarman23-Apr-21 0:06 
QuestionHow to access incrementing ID number in SQL CE? Pin
Alex Dunlop22-Apr-21 5:49
Alex Dunlop22-Apr-21 5:49 
AnswerRe: How to access incrementing ID number in SQL CE? Pin
OriginalGriff22-Apr-21 6:08
mveOriginalGriff22-Apr-21 6:08 
AnswerRe: How to access incrementing ID number in SQL CE? Pin
Dave Kreskowiak22-Apr-21 6:23
mveDave Kreskowiak22-Apr-21 6:23 
AnswerRe: How to access incrementing ID number in SQL CE? Pin
SeanChupas22-Apr-21 6:43
SeanChupas22-Apr-21 6:43 
QuestionHow to preserve DataGridView row and text color when using column filters? Pin
Alex Dunlop21-Apr-21 4:49
Alex Dunlop21-Apr-21 4:49 
AnswerRe: How to preserve DataGridView row and text color when using column filters? Pin
Gerry Schmitz21-Apr-21 6:22
mveGerry Schmitz21-Apr-21 6:22 
GeneralRe: How to preserve DataGridView row and text color when using column filters? Pin
Alex Dunlop21-Apr-21 6:34
Alex Dunlop21-Apr-21 6:34 
GeneralRe: How to preserve DataGridView row and text color when using column filters? Pin
Gerry Schmitz21-Apr-21 6:45
mveGerry Schmitz21-Apr-21 6:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.