Задается глобальный интервал (например, 0-1000). Есть метод write
, который принимает интервал от 0 до 200, а также строку (обозначим ее S
). Строка S
генерируется в течение нескольких минут (генерирование идет в несколько потоков), сохраняет все строки в переменную list
типа List<string>
Мне нужно в несколько потоков вызвать метод write
, посылая ему интервал за интервалом (0-200, 200-400 и т.д.), а также новую строку S
.
Я сделал так:
globalto = 1000;
globalfrom = 0;
double k = (globalto - globalfrom) ;
k /= 200;
if (k > Math.Truncate(k))
k = Math.Truncate(k) + 1;
long[] mas = new long[Convert.ToInt32(k)];
for (int i = 0; i < k; i++)
mas[i] = globalfrom += 200;
mas.AsParallel().WithDegreeOfParallelism(thread).ForAll(j => write(j - 200, j, ""));
Но тут я не посылаю строку S
. Не знаю как правильно реализовать, чтобы как только в переменной list
появлялась строка, сразу создавался поток, который вызовет метод write
, посылая текущую строку и новый отрезок, и чтобы всё это продолжалось до тех пор, пока не будет достигнут конец глобального интервала (0-1000).
Вариация Поставщик/Потребитель, применимая к вашей задаче
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main() => new Program().Run();
Random Rnd = new Random();
ConcurrentQueue<Interval> Items = new ConcurrentQueue<Interval>();
int bigSegment = 2000;
int smallSegment = 200;
bool HasFinished = false;
void Run()
{
// Запускаем потребителей
var consumers = Enumerable.Range(0, 5)
.Select(i => Task.Run(() => Consumer(i)))
.ToArray();
// Запускаем поставщиков
var producers = Enumerable.Range(0, bigSegment / smallSegment)
.Select(i => Task.Run(() => Producer(i)))
.ToArray();
// Ждем всех поставщиков
Task.WaitAll(producers);
// Ставим глобальный флаг
HasFinished = true;
// Ждем всех потребителей
Task.WaitAll(consumers);
Console.WriteLine("Работа завершена!");
Console.ReadLine();
}
void Producer(int num)
{
Thread.Sleep(Rnd.Next(10) * 200); // Имитация продолжительной работы
// Добавляем сгенерированный элемент в коллекцию
Items.Enqueue(new Interval { Num = num, S = $"Строка {num}" });
Console.WriteLine($"Поставщик {num} закончил работу");
}
void Consumer(int num)
{
while (!HasFinished)
{
while (!Items.IsEmpty)
{
// Пробуем извлечь элемент из коллекции
if (Items.TryDequeue(out var item))
WriteAsync(item, num);
}
Thread.Sleep(100); // Спим 0,1 с
}
Console.WriteLine($"Потребитель {num} закончил работу");
}
void WriteAsync(Interval item, int num)
{
Thread.Sleep(Rnd.Next(10) * 100); // Имитация продолжительной работы
Console.WriteLine($"Потребитель {num}: интревал {item.Num * smallSegment} - {(item.Num + 1) * smallSegment}, {item.S}");
}
}
struct Interval
{
public int Num { get; set; }
public string S { get; set; }
}
Рекомендую изучить дополнительно ответы в этом вопросе: Имплементация Producer/Consumer pattern
namespace ConsoleApplication1
{
internal class Program
{
static List<string> list= new List<string>();
private static void Main(string[] args)
{
int globalto = 1000;
int globalfrom = 0;
int length = 200;
for (int i=0; globalfrom +i*length<globalto;i++)
{
myFunc(globalfrom + i * length, Math.Min(globalfrom + (i+1) * length, globalto),i);
}
}
private static async void myFunc(int from, int to,int number)
{
while (list.Count <= number)
{
await Task.Delay(TimeSpan.FromMilliseconds(50));
}
write(from, to, list[string]);
}
}
}
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Есть проблема при отображении UserCotrol'a в дизайнере, в конструкторе UserControl'a есть следующий код
Добрый день, собственно настало то время когда мне нужно работать с массивом байтов, а я в них ни тю, тю, изучал их мельком, собственно суть...
Привет! Помогите создать таймер на 1 час в юнити; нужно что бы через каждый час происходило действие
Здравствуйте, на Hackerrank решил задачу о размене монет с использованием мемоизацииОднако, мне моё решение, кажется не очень оптимальным