Sarmeu
Sarmeu

Reputation: 95

Enhance performance for threading

I have an app with a start button that calls a long running time function. In order to add a Stop button I've added a thread for this function to avoid the UI freezes and be able to stop the processing in anytime.

The code without threading in average takes 12 minutes to complete the processing, but with threading in the way I have below takes 4 times more. Below is shown the code for the start button where is called the function "LongRunningFunction" . The function needs a string argument to work "LongRunningFunction(Somestring)".

I've tested with Task.Run and Task.Factory.StartNew but it happens the same with both methods.

Is there an alternative way to set a thread for my case that doesn't affect too much the performance?

public partial class Form1 : Form
{
    CancellationTokenSource cts = new CancellationTokenSource(); // Create the token source.
    public Form1()
    {
        InitializeComponent();
    }
    private void Start_Click(object sender, EventArgs e)
    {
        if (cts != null)
        {
            cts.Cancel();
        }
        cts = new CancellationTokenSource();
        Task.Run(()=> LongRunningFunction(Somestring, cts.Token), cts.Token);            
        //Task.Factory.StartNew(() => LongRunningFunction(Somestring, cts.Token), cts.Token, TaskCreationOptions.None, TaskScheduler.Default); 
    }
    private void Stop_Click(object sender, EventArgs e)
    {
        if (cts != null)
        {
            cts.Cancel();
            cts = null;
            MessageBox.Show("Processing cancelled");
        }
    }
    public void LongRunningFunction(string String, CancellationToken token)
    {
        //Long running processing
        //...
        MessageBox.Show("Processing finished");
    }
}

Update: The only what I changed is the way I declare the function and added an if statement inside the while loop that is inside the function. Is like below:

Without thread I declare the function like this:

public void LongRunningFunction(string String) 
{ 
    while (condition)
    {
        //My code within While loop
    }
    MessageBox.Show("Processing finished");
}

and with Thread I define the function like this:

public void LongRunningFunction(string String, CancellationToken token) 
{ 
    while (condition)
    {
        if (token.IsCancellationRequested)
        {
            break;
        }       
        //My code within While loop
    }
    if (!token.IsCancellationRequested)
    {
        MessageBox.Show("Processing finished");
    }       
}

Update2: Inside LongRunningFunction() is called another function that prints the lines. Is like below.

    public void LongRunningFunction(string fileName, CancellationToken token)
    {
        StreamWriter writer = new StreamWriter(@outputfile, true, Encoding.UTF8, 4096);

        using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
        {
            List<byte> buffer = new List<byte>();
            List<string> buffer1 = new List<string>();

            SoapHexBinary hex = new SoapHexBinary();

            while (chunk.Length > 0)
            {
                if (token.IsCancellationRequested) // ### For Cancel Thread ###
                {
                    break;
                }   // ### For Cancel Thread ###    

                    chunk = reader.ReadBytes(1024);

                    foreach (byte data in chunk)
                    {
                        if (somecondition)
                        {
                            buffer.Add(data);                           
                        }
                        else if (other condition)
                        {
                            buffer.Add(data);
                            PrintFunction(buffer, hex, outputfile, writer); // Print Line
                        }
                        else if (some other condition)
                        {
                            buffer.Add(data);
                        }
                    }                   
            }           
            if (!token.IsCancellationRequested)
            {
                MessageBox.Show("Processing finished");
            }

        }

        if (writer != null)
        {
            writer.Dispose();
            writer.Close();
        }
    }       
    private void PrintFunction(List<byte> buffer, SoapHexBinary hex, string outputfile, StreamWriter writer)
    {
            if (buffer.Count > 0)
            {
                if (buffer.Count >= lowlimit)
                {
                    hex.Value = buffer.ToArray();
                    string Register = hex.ToString();

                    Regex pattern1 = new Regex(@"some pattern");

                    if (pattern1.IsMatch(Register))
                    {
                        Match l1 = Regex.Match(Register, @"somepattern", RegexOptions.IgnoreCase | RegexOptions.Compiled);
                        writer.Write("{0}|{1}|{2}", Convert.ToInt32(l1.Groups[1].ToString(), 16), l1.Groups[2].Value, l1.Groups[3].Value);
                        Match l2 = Regex.Match(Register, @"otherpattern", RegexOptions.IgnoreCase | RegexOptions.Compiled);
                        if (l2.Success)
                        {
                            foreach (Match m in Regex.Matches(l2.Groups[2].ToString(), pattern2, RegexOptions.IgnoreCase | RegexOptions.Compiled))
                            {
                                //Some foreach code
                            }
                            foreach (Match x in Regex.Matches(var, @"pattern"))
                            {
                                //come code
                            }
                            writer.WriteLine("," + String.Join(",", var1));
                        }
                        else
                        {
                            writer.WriteLine();
                        }
                    }
                }
            }
            buffer.Clear();
    }

Update3: Hi bebosh,

I still have doubts how to apply in my function, the way you define the delegate in your example function.

My function looks like this:

public void LongRunningFunction(string fileName)
{
    using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
    {
        // some code
    }
}       

It could be something like this or how?:

private void LongRunningFunction(string fileName)
{
    MethodInvoker action = delegate
    {
        using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
        {
            // some code
        }
    };
}

Upvotes: 0

Views: 294

Answers (3)

bebosh
bebosh

Reputation: 863

Could you try this code:

    bool Stop = false;
    Thread thread;

    private void StartButton_Click(object sender, EventArgs e)
    {
        string FileName = @"...\a.bin";
        thread = new Thread(new ThreadStart(() => DoLongProcess(FileName)));
        thread.IsBackground = true;
        thread.Start();
    }

    private void StopButton_Click(object sender, EventArgs e)
    {
        Stop = true;
    }


    private void DoLongProcess(string file)
    {
        using (BinaryReader reader = new BinaryReader(File.Open(file, FileMode.Open)))
        {
            int pos = 0;
            int length = (int)reader.BaseStream.Length;
            while (pos < length)
            {
                if (Stop)
                    thread.Abort();
                // using Invoke if you want cross UI objects
                this.Invoke((MethodInvoker)delegate
                {
                    label1.Text = pos.ToString();
                });
                pos += sizeof(int);
            }
        }
    }

Upvotes: 1

Artak
Artak

Reputation: 2887

Bebosh's answer was good enough. To increase the performance further you can set the ThreadPriority of the "thread" by setting the ".Priority = ThreadPriority.AboveNormal" right after setting the "thread.IsBackground = true;".

Upvotes: 2

Mojtaba Khooryani
Mojtaba Khooryani

Reputation: 1875

use interrupting the thread

        Thread thread;

        public MainWindow()
        {
            InitializeComponent();
        }

        private async void StartButtonClick(object sender, RoutedEventArgs e)
        {
            thread = new Thread(ExecuteLong);
            var task = Task.Run(() =>
                thread.Start());
            await task;
        }

        private void ExecuteLong()
        {
            try
            {
                // long task
            }
            catch (ThreadInterruptedException e)
            {
                MessageBox.Show("cancelled!");
                return;
            }
            MessageBox.Show("finished");
        }

        private void CancelButtonClick(object sender, RoutedEventArgs e)
        {
            this.thread.Interrupt();
        }

Upvotes: -1

Related Questions