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;
}
}
}