Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WinForms, .Net Framework Новый топик    Ответить
Топик располагается на нескольких страницах: Ctrl  назад   1 2 [3]      все
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4831
WaspNewCore

не смотрел код Task.WhenAll, но если там что-то типа
foreach (var element in enumerable)
  await element;



Там такая мутота
	List<Task> list = new List<Task>();
	foreach (Task task2 in tasks)
	{
		if (task2 == null)
		{
			throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
		}
		list.Add(task2);
	}
	return Task.InternalWhenAll(list.ToArray());
20 авг 18, 15:49    [21648331]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4831
Вообще, по хорошему, нужна система с обратной связью, т. е. на каждой итерации увеличиваешь количество потоков/тасков, до тез пор, пока растет итоговая производительность и не увеличиваешь/понижаешь когда итоговая производительность начинает падать.
await/async тут тебе не нужно.
Ну и как правило нужно улучшить производительность БД, созданием индексов/статистик/мат. view и протиранием монитора.
20 авг 18, 16:03    [21648352]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
ЕвгенийВ
await/async тут тебе не нужно


При наличии I/O весьма полезен.

Систему с обратной связью покажи )
20 авг 18, 16:12    [21648365]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
WaspNewCore
Member

Откуда:
Сообщений: 151
ЕвгенийВ,

Интересно. Какой прок тогда принимать IEnumerable, если все сводится к ToArray.
Наверное ради того, чтобы собрать результат работы всех тасков, чтобы потом выбросить AggregateException. Но даже в этом случае не лучше ли было работать с List в который динамически добавлять каждую задачу после ее ожидания.

Ну. Не нам судить профи, скорее всего причина все таки у них есть, просто нужно изучать код. Причина скорее всего есть, я верю в профессионализм разрабов C#.

В любом случае, как я сказал выше, на достаточно небольшом числе задач, указанный метод вполне рабочий. Буду его пока придерживаться.
20 авг 18, 16:13    [21648368]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4831
hVostt

Систему с обратной связью покажи )

Как то так.
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Diagnostics;
using Profiling;
using System.IO;

namespace Leo.Loader.Service
{
    public class RmqThreadManagerConsumer2<T> where T : class
    {
        static object Locker = new object();
        Func<Tuple<T[], string, Action>> _getter;
        Action<T> _runner;
        ConcurrentQueue<double> concurrentQueue = new ConcurrentQueue<double>();
        System.Timers.Timer timer2;
        volatile int Counter;
        Logics.FileWriter inputFileWriter;// = new Logics.FileWriter(System.Configuration.ConfigurationManager.AppSettings[])
        Logics.FileWriter errorFileWriter;
        public RmqThreadManagerConsumer2(Func<Tuple<T[], string, Action>> getter, Action<T> runner, string queueName, string inputRoot, string errorRoot)
        {
            _getter = getter ?? throw new ArgumentNullException(nameof(getter));
            _runner = runner ?? throw new ArgumentNullException(nameof(runner));
            if (string.IsNullOrEmpty(queueName))
                throw new ArgumentNullException(nameof(queueName));
            inputFileWriter = new Logics.FileWriter(inputRoot);
            errorFileWriter = new Logics.FileWriter(errorRoot);
            timer2 = new System.Timers.Timer(1000);
            timer2.SynchronizingObject = new SynchronizeInvoke();
            timer2.Elapsed += (o, a) => 
            {
                Run();
            };
            timer2.Start();
        }

        void Run()
        {
            lock (Locker)
            {
                Measure();
            }
        }
        void Grow(double d)
        {
            var agg = concurrentQueue.Count < 1 ? 1 : concurrentQueue.Count;
            var summ = concurrentQueue.Sum();
            var avg = summ / agg;
            Console.WriteLine("avg-" + avg);
            if ((1.1*d) > avg)//время выросло
            {
                if (Counter > 2)
                    Counter--;
            }
            else//время уменьшилось
            {
                if (Counter < 100)
                    Counter++;
            }
            concurrentQueue.Enqueue(d);
            if (agg > 100)
            {
                concurrentQueue.TryDequeue(out double x);
            }
        }
        void Measure()
        {
            Tuple<T[], string, Action> t = null;
            try
            {
                var c = Counter;

                while (c-- >= 0)
                {
                    Stopwatch sv = new Stopwatch();
                    bool IsNull = false;
                    t = _getter();
                    var res = Task.Factory.StartNew(() =>
                    {
                        sv.Start();
                        
                        if (t?.Item1 == null)
                        {
                            IsNull = true;
                            return;
                        }
                        foreach (var x in t.Item1)
                        {
                            _runner(x);
                        }
                        if (!string.IsNullOrEmpty(t.Item2))
                        {
                            lock (inputFileWriter)
                            {
                                inputFileWriter.Write(DateTime.Now, t.Item2, Path.GetRandomFileName() + ".json");
                            }
                        }
                    }).ContinueWith(task =>
                    {
                        var exc = task.Exception;
                        sv.Stop();
                        if (!IsNull)
                            Grow(sv.ElapsedMilliseconds);
                    });
                    var sdf = res.Exception;
                    if (sdf != null)
                    {
                        Logger.Instance.Error(sdf);
                        continue;
                    }
                    //помечаем сообщение обработанным
                    t?.Item3?.Invoke();
                    //res.Wait();
                }
            }
            catch (Exception exc)
            {
                Logger.Instance.Error(exc, "Ошибка в Measure");
                lock (errorFileWriter)
                {
                    errorFileWriter.Write(DateTime.Now, t?.Item2, Path.GetRandomFileName() + ".json");
                }
            }
        }
    }
}
20 авг 18, 16:39    [21648398]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
ЕвгенийВ,

спасибо, потестирую в ближайшее время :)
21 авг 18, 11:05    [21649103]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4831
hVostt
ЕвгенийВ,

спасибо, потестирую в ближайшее время :)

Хорошо. Это только идея и первая реализация в лоб.
21 авг 18, 11:14    [21649129]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 2 [3]      все
Все форумы / WinForms, .Net Framework Ответить