Генерация строки в несколько потоков по интервалам

287
02 августа 2017, 18:26

Задается глобальный интервал (например, 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).

Answer 1

Вариация Поставщик/Потребитель, применимая к вашей задаче

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

Answer 2
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]);
    }
}
}
READ ALSO
Относительный путь в UserControl

Относительный путь в UserControl

Есть проблема при отображении UserCotrol'a в дизайнере, в конструкторе UserControl'a есть следующий код

253
Работа с массивом байтов C#

Работа с массивом байтов C#

Добрый день, собственно настало то время когда мне нужно работать с массивом байтов, а я в них ни тю, тю, изучал их мельком, собственно суть...

363
Таймер на 1 час в Unity3D

Таймер на 1 час в Unity3D

Привет! Помогите создать таймер на 1 час в юнити; нужно что бы через каждый час происходило действие

271
задача о размене монет (Coin change problem)

задача о размене монет (Coin change problem)

Здравствуйте, на Hackerrank решил задачу о размене монет с использованием мемоизацииОднако, мне моё решение, кажется не очень оптимальным

438