Выполнение работоспособных пакетов в нескольких потоках

1

Я новичок в концепции многопоточности С#/. У Net и у меня есть следующее требование.

Наше приложение должно сначала забрать клиентов (только ids), для которых необходимо выполнить обработку данных, и на основе размера WorkPacket (терминология, используемая для упаковки набора клиентов в рабочий пакет), создаются WorkPackets. Поэтому каждый рабочий пакет содержит набор клиентов

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

У нас есть функциональность с одним потоком, но мы знаем, как это можно реализовать с помощью. Ниже приведен код. Какие-либо предложения???

public class WorkAllocator
{
    private int workPacketSize;
    private List<WorkPacket> workPackets;
    public List<WorkPacket> WorkPackets
    {
        get { return workPackets; }
        set { workPackets = value; }
    }

    public int WorkPacketSize
    {
        get { return workPacketSize; }
        set { workPacketSize = value; }
    }

    public WorkAllocator(int size)
    {
        workPacketSize = size;
        int noOfPackets=0;
        DataManager objDAL = new DataManager(ConnectionString);

        IEnumerable<string> CustomerIds = objDAL.GetData();
        workPackets = new List<WorkPacket>();

        if (CustomerIds.Count() > 0)
        {
            noOfPackets = CustomerIds.Count() / workPacketSize;
            if (CustomerIds.Count() % workPacketSize != 0)
            {
                noOfPackets++;
            }

            var wps = CustomerIds
                .Select((c, i) => new { Index = i, Value = c })
                .GroupBy(c => c.Index / workPacketSize)
                .Select(c => c.Select(v => v.Value).ToList())
                .ToList();

            foreach (List<string> wp in wps)
            {
                workPackets.Add(new WorkPacket(wp));
            }
        }
        objDAL.Dispose();
    }
}

public class WorkPacket
{
    private List<string> customerIds;

    public List<string> customerIds
    {
        get { return customerIds; }
        set { customerIds = value; }
    }

    public WorkPacket(List<string> Cids)
    {
        customerIds = Cids;
    }
}

Код по основному методу

wa = new WorkAllocator(10);
if (wa.WorkPackets != null && wa.WorkPackets.Count > 0)
{
    //Dynamically Create threads for each work packets and join after all child thread completes the activity
    foreach (WorkPacket wp in wa.WorkPackets)
    {
            var _processor = new Processor();
        Processor.Run(wp);
    }
}
  • 0
    некоторые случайные мысли о коде: для noOfPackets лучше использовать Math.Ceiling . Шаг с «Select + Index-> GroupBy» будет проще, если вы добавите «номер группы» вместо индекса напрямую (выполните / прямо там) или в любом случае в качестве foreach: зациклите свои идентификаторы один раз и получите группы (проще даже если это необходимо). Кроме этого, я не вижу ничего в том, как вы делаете свои параллельные вещи - я надеюсь, что вы каким-то образом используете ThreadPool ...
  • 1
    Этот вопрос кажется не по теме, потому что речь идет о CodeReview
Показать ещё 1 комментарий
Теги:
multithreading

2 ответа

1
Лучший ответ

Простое решение с помощью Task s:

wa = new WorkAllocator(10);
if (wa.WorkPackets != null && wa.WorkPackets.Count > 0)
{
    var tasks = new List<Task>();
    foreach (WorkPacket wp in wa.WorkPackets)
    {
        tasks.Add(Task.Run(() =>
            {
                Processor.Run(wp);
            });
    }

    Task.WaitAll(tasks.ToArray());
}

Это запустит каждый Processor в своем потоке (распараллеливание, управляемое ThreadPool), а затем дождитесь завершения всех этих действий.

Возможно, посмотрите в ActionBlock, там вы можете сделать что-то вроде:

var threadCount = Environment.ProcessorCount;
var actionBlock = new ActionBlock<WorkPacket>(() => Processor.Run(wp),
   // this is optional, but default is 1:
   new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = threadCount });

wa = new WorkAllocator(10);
if (wa.WorkPackets != null && wa.WorkPackets.Count > 0)
{
    var tasks = new List<Task>();
    foreach (WorkPacket wp in wa.WorkPackets)
        actionBlock.Post(wp);

    actionBlock.Complete();
    actionBlock.Completion.Wait();
}
1

В основном методе вы можете просто использовать Parallel.ForEach. Это блокировка - не будет возвращаться до обработки всех рабочих пакетов.

Parallel.ForEach(wa.WorkPackets, wp => Processor.Run(wp));

Ещё вопросы

Сообщество Overcoder
Наверх
Меню