Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.50/40: Рейтинг темы: голосов - 40, средняя оценка - 4.50
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825

Очередь запросов

11.09.2018, 23:26. Показов 8225. Ответов 44
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, форумчане. Такой вопрос.. Есть софтина, которая обращается к апи одно сервиса, из месяца в месяц обрастала функционалом, когда-то хватало выставить дефолт таймаут между запросами, потом было прикручено регулирование таймаута, но сейчас уже и этого не хватает, т.к из разных функций и потоков, отправляет запросы и таймауты уже не помогают регулировать кол-во запросов в секунду. Из-за превышения ключ сносит, что доставляет небольшой дискомфорт пользователям.
Суть вопроса в том, как сделать какую нибудь очередь запросов в одном месте, чтобы регулировать кол-во отправленных запросов таймаутом из одного места? Надеюсь вы меня поняли.. Для запросов использую xNet
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.09.2018, 23:26
Ответы с готовыми решениями:

Очередь выполнения множества запросов и рано или поздно наступающий StackOverflow
Вообщем имеется очередь выполнения: в очередь кладется команда (например, выполнение sql запроса) и потом в 1 потоке выполняются все...

Web api Управлять очередью запросов динамически (длиной) и как получить url поступившего в очередь запроса
Я так понимаю, что все запросы приходят в HTTP.Sys откуда запрос в виде HTTP.Context поступает на web api. И все параметры HTTP.Sys нужно...

Очередь запросов и их выполнение
Привет, есть метод вида void task(int number), и к нему делаются асинхронные запросы, но из-за свой особенности он не асинхронный и сделать...

44
Эксперт .NET
 Аватар для Usaga
14301 / 9386 / 1353
Регистрация: 21.01.2016
Сообщений: 35,391
12.09.2018, 06:22
Цитата Сообщение от MakcPletnev Посмотреть сообщение
Суть вопроса в том, как сделать какую нибудь очередь запросов в одном месте, чтобы регулировать кол-во отправленных запросов таймаутом из одного места?
Ну, вы сами себе уже ответили: нужно это самое "одно место", через которое все сервисы приложения будут работать. В этом "одном месте" все запросы должны складываться в очередь и должен присутствовать счётчик отслеживающий и регулирующий скорость выборки и исполнения запросов из очереди.
1
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825
12.09.2018, 14:29  [ТС]
Usaga, но как это программно реализовать? У меня как-то даже мыслей нет, я же не могу ограничить вызов функции.. Ну допустим можно было бы юзать
lock(locker){
...
Thread.Sleep(1000);
}
, но он же не будет работать, если я буду с главного потока делать запрос, а если и будет, то этот слип точно будет вешать форму
0
Эксперт .NET
 Аватар для Usaga
14301 / 9386 / 1353
Регистрация: 21.01.2016
Сообщений: 35,391
12.09.2018, 17:04
MakcPletnev, конечно же, запросы должны быть асинхронными или выполняться в другом потоке.
1
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825
14.09.2018, 17:47  [ТС]
Usaga, можете хоть примерно накидать? Я никогда (за 3 года) не работал с async и await (странно, как то не требовались никогда). Я всегда просто создавал поток и в нем работала функция void, но тут так не получится, потому что нужно возвращать значение, + нужно по любому делать thread.join(), чтобы дождать окончания запроса, а из главной формы это все равно ее повесит. Подкиньте в правильное русло )) желательно примерчиком
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
15.09.2018, 14:34
MakcPletnev, если я правильно понял, то сейчас у тебя примерно так:
Есть несколько интерфейсов IAuthService, ISomeWebService (просто пример). Их реализации (конкретные классы class AuthService : IAuthService...) вызывают внутри своих методов запросы к какой-то службе напрямую. Все эти методы вызываются из многих мест в программе. Благодаря тому, что у тебя есть отдельные классы, да ещё и интерфейсы с реализацией, ты можешь просто создать новые реализаии, в методах которых будешь формировать какие-то данные, передавать в очередь, которая в несколько потоков (async await, как раз это, грубо говоря, умеет), на основе этих данных будет отправлять запросы, и ограничивать их кол-во по каким-то твоим правилам.
0
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825
15.09.2018, 16:43  [ТС]
Casper-SC, я понимаю о чем вы, но не понимаю, как мне async и await поможет ограничивать кол-во запросов.
Сейчас я запрос к api отправляю примерно так из любой функции, которой нужны данные из Web для работы

string reponse = new HttpRequest().Get(....).ToString();

Добавлено через 10 минут
Я просто не понимаю, вот добавлю я ссылку в очередь (например)
как мне потом результат то получить, который отдаст выполнение запроса?
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
15.09.2018, 18:00
Цитата Сообщение от MakcPletnev Посмотреть сообщение
Я просто не понимаю, вот добавлю я ссылку в очередь (например)
как мне потом результат то получить, который отдаст выполнение запроса?
Посмотри на TaskCompletionSource<T>


Добавлено через 2 минуты
Вообще, я бы даже сказал, всё зависит от того, какая у тебя реализация, возможно, тебе это и не нужно.
0
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825
15.09.2018, 18:21  [ТС]
Casper-SC, это я понимаю) А очередь то сюда как пихнуть?
0
Эксперт .NET
 Аватар для Usaga
14301 / 9386 / 1353
Регистрация: 21.01.2016
Сообщений: 35,391
16.09.2018, 05:54
MakcPletnev, я имел в виду подход заворачивания вашей задачи обращения к серверу в отдельный класс и передачи объекта этого класса в сервис-исполнятор, который будет эти задачи складывать в очередь и потихоньку выполнять следя, чтобы одновременно не работало более N задач.

Простой и грубый вариант может выглядеть примерно так:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
 
namespace ConsoleAppExperimets
{
    interface ISomeServerRequest
    {
        object SomeResult { get; set; }
        void Run();
    }
 
    class SomeServerRequest : ISomeServerRequest
    {
        private readonly string someParam;
 
        public object SomeResult { get; set; }
 
        public SomeServerRequest(string someParam)
        {
            this.someParam = someParam;
        }
 
        public void Run()
        {
            // обращение к серверу или вообще любая долгая работа
            this.SomeResult = "some result";
        }
    }
 
    class LongTaskRunner
    {
        private ConcurrentQueue<Task<ISomeServerRequest>> tasks 
            = new ConcurrentQueue<Task<ISomeServerRequest>>();
        private volatile int tasksRunningCounter = 0;
        private object locker = new object();
 
        // Можно сделать конфигурируемой настройкой
        private const int MaxParallelTasks = 6;
 
        public Task<ISomeServerRequest> AddTask(ISomeServerRequest task)
        {
            var t = new Task<ISomeServerRequest>(() => { task.Run(); return task; });
            tasks.Enqueue(t);
 
            t.GetAwaiter().OnCompleted(() => TaskDone());
 
            RunTasksTillLimit();
            return t;
        }
 
        private void RunTasksTillLimit()
        {
            lock (locker)
            {
                while (true)
                {
                    var count = tasksRunningCounter;
                    if (count >= MaxParallelTasks)
                        return;
 
                    if (tasks.TryDequeue(out var t))
                    {
                        t.Start();
                        tasksRunningCounter++;
                    }
                    else
                    {
                        return;
                    }
                }
            }
        }
 
        private void TaskDone()
        {
            lock (locker)
            {
                tasksRunningCounter--;
                RunTasksTillLimit();
            }
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            //На самом деле, экземпляр LongTaskRunner надо держать в одном экземпляре
            var taskRunner = new LongTaskRunner();
 
            var request = new SomeServerRequest("adfads");
            taskRunner.AddTask(request).ContinueWith(r => {
                //Это выполняется после успешного завершения запроса
                //Не обязательна именно лямбда, можно и метод вызвать
                Console.WriteLine(r.Result.SomeResult);
            });
 
            Console.WriteLine("done");
            Console.ReadKey();
        }
    }
}
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
16.09.2018, 10:29
del
0
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825
16.09.2018, 15:26  [ТС]
Usaga, оу, можно даже так? Я обязательно ознакомлюсь с вашим примером, почитаю документацию по таскам. Спасибо большое!)
Просто программирование тасков больше напоминает мне что-то типа Promise и Subscribe в Angular, не думал , что такая конструкция возможна на C#. В очередной раз убеждаюсь, что возможно все)
0
12 / 12 / 5
Регистрация: 29.07.2016
Сообщений: 164
16.09.2018, 17:07
Вроде бы еще не было, можно еще сделать свою перегрузку Client.Post/Get и там сделать оболочку над стандартным запросом и регулировать таймауты.
0
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825
17.09.2018, 02:30  [ТС]
fan92rus, в случае xNet нельзя, нет наследования , чтобы сделать перегрузку. Если я правильно понял ваш посыл..
0
12 / 12 / 5
Регистрация: 29.07.2016
Сообщений: 164
17.09.2018, 08:34
Вот так работает, хотя может быть я не понял
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApp10
{
    class Program
    {
        static void Main(string[] args)
        {
            HttpRequest client = new HttpRequest();
            client.Get("");
        }
    }
    class HttpRequest:xNet.Net.HttpRequest
    {
        static object locker = new object();
 
        public void Get(string addres)
        {
            lock(locker)
            {
                this.Get(addres);
            }
        }
    }
}
0
Эксперт .NET
 Аватар для Usaga
14301 / 9386 / 1353
Регистрация: 21.01.2016
Сообщений: 35,391
17.09.2018, 08:37
fan92rus, довольно так себе подход. Действительно, более одного запроса выполняться не будет, но все остальные потоки тупо встанут колом на локе.
0
12 / 12 / 5
Регистрация: 29.07.2016
Сообщений: 164
17.09.2018, 09:07
Это пример, тут можно юзать свои ограничения, ну или семафор. В любом случае писать модуль управления таймаутами.
1
Эксперт .NET
 Аватар для Usaga
14301 / 9386 / 1353
Регистрация: 21.01.2016
Сообщений: 35,391
17.09.2018, 09:30
fan92rus, lock и семафор тут не особо хорошо подойдут. Получается, что все обращения к серверу будут запускаться сразу, но будут упираться в блокировку. И выходить из неё они будут в произвольном порядке. Т.е. порядок исполнения запросов будет неопределён, а в приложении будет висеть N заблокированных потоков. Очень нехорошее решение.

Уместнее именно очередь применить. Запускать потоки только тогда, когда можно, а не всё в кучу и неугодных локами стопорить.
1
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825
17.09.2018, 15:18  [ТС]
В любом случае спасибо всем за помощь) С помощью варианта fan92rus, очень легко сделать логирование запросов (если конечно очередь не используется). Может кому-то будет нужно
0
12 / 12 / 5
Регистрация: 29.07.2016
Сообщений: 164
17.09.2018, 19:13
Если еще надо, накидаю завтра модуль управления очередью, если можно то отелось бы вариант сортировки очереди, как ее регулировать
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.09.2018, 19:13
Помогаю со студенческими работами здесь

Очередь отправки get-запросов
Есть get запрос: http://158.4581/sad.php?id=&amp;auth= И есть содержимое в richTextBox1 такого типа: ...

Разработка модели обследования запросов (процессов) с использованием дисциплины, типа Очередь
Разработка модели обследования запросов (процессов) с помощью дисциплины, типа Очередь

Очередь XML запросов
Доброе время суток. Задача: выполнить очередь XML запросов, причем так, чтобы страница была доступна для &quot;кликания&quot; во время...

Сформировать очередь по файлу целых чисел. Промоделировать очередь в супермаркете
Сформировать очередь по файлу целых чисел. Промоделировать очередь в супермаркете. В каждый момент времени происходит одно из событий:...

Очередь (сделать очередь, чтобы добавляло, удаляло, читало. Не STL.)
Помогите пожалуйста написать очередь. Есть Температура double и ее тип int ну и нужно сделать очередь, чтобы добавляло, удаляло, читало....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru