Основы параллельного ввода-вывода - PullRequest
0 голосов
/ 03 октября 2018

Я борюсь с параллелизмом в c # и связанным с ним шаблоном асинхронного ожидания.

Я столкнулся с проблемой производительности, потому что мне нужно использовать несколько провайдеров БД._schedulesProvider содержит различные провайдеры.Я действительно не хочу ничего там менять, но моя идея состояла в том, чтобы выполнить эти дорогостоящие операции ввода-вывода одновременно.Я знаю, что было бы идеально использовать await async здесь, чтобы не блокировать вызывающий поток во время ожидания завершения операций ввода-вывода, но в данный момент я не очень беспокоюсь об этом.

рассмотрите следующий код:

//queuing all the expensive code in tasks
    List<Task> scheduleProviderTasks = _schedulesProvider.Select(scheduleProvider =>
                {
                    return
                            Task.Run(() =>
                            {
//expensive I/O operation
                                var schedules = scheduleProvider.Get();

                                if (!schedules.Schedules.Any())
                                {
                                    return;
                                }

//do some stuff with the result
                                schedules.Schedules.ForEach(x =>
                                {
                                   DoSomething(x);

                                });
                            });


                }).ToList();

//run all tasks
scheduleProviderTasks.ForEach(x=>x.RunSynchronously());

что я ожидаю:

затраты на эту операцию теперь должны быть намного ниже, поскольку дорогостоящие операции выполняются параллельно.

текущий поток блокируется до scheduleProviderTasks.ForEach(x=>x.RunSynchronously());

и, следовательно, все операции завершены.

Это правда?Должен ли я рефакторинг этого кода?

1 Ответ

0 голосов
/ 03 октября 2018

Мне интересно, может ли Task.WaitAll быть полезен в вашей ситуации.

Ниже приведен пример выполнения 4-х задач по 1 секунде параллельно, где общее время составляет 2,6706808 секунд.

class Program
{
    static void Main(string[] args)
    {           
        mStopWatch.Start();
        Task[] awaitTasks = mTasks.Select(aTask => Task.Run(() => aTask.TimeConsumingTask())).ToArray();
        Task.WaitAll(awaitTasks);
        Debug.WriteLine("Done @ " + mStopWatch.Elapsed.ToString());
    }
    static Stopwatch mStopWatch = new Stopwatch();
    static ProviderOfLengthyTask[] mTasks = new ProviderOfLengthyTask[]
    {
        new ProviderOfLengthyTask("A"),
        new ProviderOfLengthyTask("B"),
        new ProviderOfLengthyTask("C"),
        new ProviderOfLengthyTask("D")
    };
    class ProviderOfLengthyTask
    {
        public ProviderOfLengthyTask(string name)
        {
            Name = name;
        }
        public readonly string Name;
        public void TimeConsumingTask()
        {
            Thread.Sleep(1000);
            Debug.WriteLine("Done with " + Name + " @ " + mStopWatch.Elapsed.ToString());
        }
    }
}

Где вывод:

Готово с B @ 00: 00: 01.0638455

Готово с A @ 00: 00: 01.0673050

Готово с D @00: 00: 02.5961501

Готово с C @ 00: 00: 02.5962068

Готово @ 00: 00: 02.6706808

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