A
A
Anton20012021-05-07 16:07:03
.NET
Anton2001, 2021-05-07 16:07:03

How to add multithreading to this code?

Hello, such a task. There is code that runs in one thread. How to add the possibility of multithreading to increase the speed of work?
Source code https://drive.google.com/file/d/1_ku66JJ4FWuiwIUk7...

There was an idea to make a List and add lines from the loop to it. And then make a function that will pull strings from the list and process them. Run a function in 20-30 threads.
But there was an error because there are too many lines and the List does not withstand (I have 16 operatives) and crashes. In general, I need help, which I just did not try.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
V
Vladimir Korotenko, 2021-05-07
@firedragon

I haven't seen the code, but do it like this
Select arguments and add tasks to the task array
Then use Task.WaitAll(taskSrray)

V
Vasily Bannikov, 2021-05-07
@vabka

Remove the link to the google drive - no one will try to find the discussed code in your archive.
If there are many lines, do not process them all at once, but in a stream.
Use channels from System.Threading.Changels for this
. The number of simultaneous threads must be equal to the number of cores - otherwise there will be no growth.

A
Anton2001, 2021-05-07
@Anton2001

Here is the code
textBox1.Text = "12foa9f";

string key = "";
        char StartChar = '1';
        bool lifeWork = false;
        int line = 0, success = 0;
        private void button1_Click(object sender, EventArgs e)
        {
            key = textBox1.Text;
            StartChar = Convert.ToChar(textBox1.Text.Substring(0, 1));
            timerLog.Interval = 900;
            timerLog.Enabled = true;
            lifeWork = true;
            Thread thr = new Thread(Work);
            thr.Start();
        }
        private void Work()
        {
            long value = EncodeBase36(key);
 
            while (lifeWork)
            {
                long newValue = value - 1;
                if (StartChar != Convert.ToChar(DecodeBase36(newValue).Substring(0, 1)))
                {
                    break;
                }
                line++;
                GetResponce(DecodeBase36(newValue));
                value = newValue;
            }
            MessageBox.Show("Off work");
        }
 
        private void GetResponce(string value)
        {
            // Тут будет происходить гет запрос на сайт с использованием value и прочая работа с строкой . По времени занимает от 5 до 15 секунд.
            // Так что код сделла чисто для симуляции времени работы .
            Random rnd = new Random();
            int timeOutn = rnd.Next(5, 15);
            Thread.Sleep(timeOutn * 1000);
            success++;
        }
        public static long EncodeBase36(string number, int radix = 36)
        {
            const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
            if (radix < 2 || radix > Digits.Length)
                throw new ArgumentException("The radix must be >= 2 and <= " +
                    Digits.Length.ToString());
 
            if (String.IsNullOrEmpty(number))
                return 0;
 
            // Make sure the arbitrary numeral system number is in upper case
            number = number.ToUpperInvariant();
 
            long result = 0;
            long multiplier = 1;
            for (int i = number.Length - 1; i >= 0; i--)
            {
                char c = number[i];
                if (i == 0 && c == '-')
                {
                    // This is the negative sign symbol
                    result = -result;
                    break;
                }
 
                int digit = Digits.IndexOf(c);
                if (digit == -1)
                    throw new ArgumentException(
                        "Invalid character in the arbitrary numeral system number",
                        "number");
 
                result += digit * multiplier;
                multiplier *= radix;
            }
 
            return result;
        }
 
        private void timerLog_Tick(object sender, EventArgs e)
        {
            lbLine.Text = line.ToString();
            lbSuccess.Text = success.ToString();
        }
 
        public static string DecodeBase36(long decimalNumber, int radix = 36)
        {
            const int BitsInLong = 64;
            const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
            if (radix < 2 || radix > Digits.Length)
                throw new ArgumentException("The radix must be >= 2 and <= " +
                    Digits.Length.ToString());
 
            if (decimalNumber == 0)
                return "0";
 
            int index = BitsInLong - 1;
            long currentNumber = Math.Abs(decimalNumber);
            char[] charArray = new char[BitsInLong];
 
            while (currentNumber != 0)
            {
                int remainder = (int)(currentNumber % radix);
                charArray[index--] = Digits[remainder];
                currentNumber = currentNumber / radix;
            }
 
            string result = new String(charArray, index + 1, BitsInLong - index - 1);
            if (decimalNumber < 0)
            {
                result = "-" + result;
            }
 
            return result;
        }

N
none7, 2021-05-08
@none7

You create a function with yield return to enumerate all numbers. Create Semaphore(30, 30). Then, sorting through these numbers foreach, you block the semaphore (one of 30 slots) and launch tasks that release the semaphore upon completion. But we must not forget that exiting foreach does not mean the completion of all tasks, and we should also not forget about synchronization.
Something like this:

spoiler

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        string key = "";
        char StartChar = '1';
        bool lifeWork = false;
        int line = 0, success = 0;
        private void button1_Click(object sender, EventArgs e)
        {
            key = textBox1.Text;
            StartChar = Convert.ToChar(textBox1.Text.Substring(0, 1));
            timerLog.Interval = 100;
            timerLog.Enabled = true;
            lifeWork = true;
            _ = Work();
        }

        IEnumerable<long> GetWorks(string key)
        {
            long value = EncodeBase36(key);

            while (true)
            {
                long newValue = value - 1;
                if (StartChar != Convert.ToChar(DecodeBase36(newValue).Substring(0, 1)))
                {
                    break;
                }
                yield return newValue;
                value = newValue;
            }
        }
        private async Task Work()
        {
            var set = new HashSet<Task>();
            var jobsSim = new SemaphoreSlim(30, 30);
            var lockSim = new SemaphoreSlim(1, 1);

            foreach(var value in GetWorks(key))
            {
                if (!lifeWork) break;

                // ограничиваем число потоков
                // по большей части лимит нужен, чтобы не зафлудить сервер запросами
                await jobsSim.WaitAsync();
                Task task = GetResponce(DecodeBase36(value));
                await lockSim.WaitAsync();
                set.Add(task);
                lockSim.Release();
                _ = task.ContinueWith(async(t) => {
                    await lockSim.WaitAsync();
                    success++;
                    set.Remove(t);
                    lockSim.Release();
                    jobsSim.Release();
                });
                line++;
            }

            await lockSim.WaitAsync();
            var tasks = set.ToList();
            lockSim.Release();

            await Task.WhenAll(tasks);

            MessageBox.Show("Off work");
        }
        private async Task GetResponce(string value)
        {
            // Тут будет происходить гет запрос и прочая работа с строкой . По времени занимает от 5 до 15 секунд.
            // Так что код сделла чисто для симуляции времени работы .
            Random rnd = new Random();
            int timeOutn = rnd.Next(5, 15);
            await Task.Delay(timeOutn * 1000);
        }
        public static long EncodeBase36(string number, int radix = 36)
        {
            const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

            if (radix < 2 || radix > Digits.Length)
                throw new ArgumentException("The radix must be >= 2 and <= " +
                    Digits.Length.ToString());

            if (String.IsNullOrEmpty(number))
                return 0;

            // Make sure the arbitrary numeral system number is in upper case
            number = number.ToUpperInvariant();

            long result = 0;
            long multiplier = 1;
            for (int i = number.Length - 1; i >= 0; i--)
            {
                char c = number[i];
                if (i == 0 && c == '-')
                {
                    // This is the negative sign symbol
                    result = -result;
                    break;
                }

                int digit = Digits.IndexOf(c);
                if (digit == -1)
                    throw new ArgumentException(
                        "Invalid character in the arbitrary numeral system number",
                        "number");

                result += digit * multiplier;
                multiplier *= radix;
            }

            return result;
        }

        private void timerLog_Tick(object sender, EventArgs e)
        {
            lbLine.Text = line.ToString();
            lbSuccess.Text = success.ToString();
        }

        public static string DecodeBase36(long decimalNumber, int radix = 36)
        {
            const int BitsInLong = 64;
            const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

            if (radix < 2 || radix > Digits.Length)
                throw new ArgumentException("The radix must be >= 2 and <= " +
                    Digits.Length.ToString());

            if (decimalNumber == 0)
                return "0";

            int index = BitsInLong - 1;
            long currentNumber = Math.Abs(decimalNumber);
            char[] charArray = new char[BitsInLong];

            while (currentNumber != 0)
            {
                int remainder = (int)(currentNumber % radix);
                charArray[index--] = Digits[remainder];
                currentNumber = currentNumber / radix;
            }

            string result = new String(charArray, index + 1, BitsInLong - index - 1);
            if (decimalNumber < 0)
            {
                result = "-" + result;
            }

            return result;
        }
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question