Answer the question
In order to leave comments, you need to log in
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
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)
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.
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;
}
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:
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 questionAsk a Question
731 491 924 answers to any question