3

Пример от andreycha паттерна throttling:

public async Task CheckServers()
{
    var servers = new List<string>(10000) { ... };

    const int ConcurrencyLevel = 100;

    // запускаем первые 100 запросов
    var tasks = servers.Take(ConcurrencyLevel).Select(GetVersion).ToList();
    int nextIndex = ConcurrencyLevel;

    while (tasks.Count > 0)
    {
        // дожидаемся завершения любого запроса
        var completedTask = await Task.WhenAny(tasks);

        // удаляем его из списка
        tasks.Remove(completedTask);

        // добавляем новый запрос, если таковые остались
        if (nextIndex < servers.Count)
        {
            tasks.Add(GetVersion(servers[nextIndex++]));
        }

        string rfbVersion = await completedTask;
        // работаем с версией
    }
}

Как в подобной реализации красиво задать параметр TaskCreationOptions.LongRunning задачам? Это вообще возможно без использования Task.Factory.StartNew?

Alexis
  • 3,476
  • Никак. Нет. Это не нужно. – Kyubey Jun 30 '16 at 17:03
  • @Athari, да ну, нужно это, ибо увеличивает на ~20-30% производительность софта если использовать Task.Factory.StartNew. Если бы от этого небыло толку, я бы не спрашивал. – Alexis Jun 30 '16 at 17:15

1 Answers1

4

Смотрите. Давайте разделим Task'и и другие асинхронные функции на те, которые ограничены процессором (то есть, занимают фиксированный поток длительное время), и остальные.

Для первых функций TaskCreationOptions.LongRunning имеет смысл, т. к. мы не хотим надолго блокировать поток из пула потоков. Но такие функции обычно предоставляются в виде синхронных функций, которые мы запускаем через Task.Run. Так что можно, при желании, запустить и через Task.Factory.StartNew.

Для остальных асинхронных функций нету понятия «поток, в котором функция бежит», и большую часть времени Task не бежит нигде, просто ожидая окончания await. Для таких функций TaskCreationOptions.LongRunning лишено смысла, и задать его сложно (если и можно вообще). Но в этом случае эта опция и не нужна.

VladD
  • 206,799
  • Работаю над увеличением скорости, это грубо говоря продолжение этого моего вопроса: http://ru.stackoverflow.com/questions/503721/%d0%9c%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d0%be%d0%b5-vs-%d0%b0%d1%81%d0%b8%d0%bd%d1%85%d1%80%d0%be%d0%bd%d0%bd%d0%be%d0%b5-%d1%81%d0%b5%d1%82%d0%b5%d0%b2%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b0%d0%ba%d1%82%d0%b8%d0%ba%d0%b5 – Alexis Jun 30 '16 at 17:17
  • В моем случае, переделав паттерн на Task.Factory.StartNew - удалось увеличить производительность, т.к. криптография протокола дает нагрузку в основном на процессор, спасибо за разъяснение. Я просто хотел узнать, есть ли способ более красиво и просто оформить код. – Alexis Jun 30 '16 at 17:18
  • 1
    @Alexis: Вроде бы другого способа нет, по крайней мере я не знаю. – VladD Jun 30 '16 at 17:23