Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
 Аватар для m0nax
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971

Async/await и свой поток, как это сделать правильно?

19.03.2016, 20:06. Показов 2454. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
короче классическая очередь задач, 1-99 потоков обрабатывают задачи по очереди

есть ли красивый и правильный путь как прикрутить async+await?
смысл возни - хочу контролировать потоки, например сделать 1 поток для обращений к базе, или 3 потока для обработки чего-нибудь-полезного, вот именно 3 конкретных потока, а не task.Run

минимальный пример рабочего, но некрасивого варианта - совершенно бессмысленный поток только ради ожидания
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
    public class Worker
    {
        Queue<Helper> tasks = new Queue<Helper>(); 
 
        public Task Execute(Action action)
        {
            Helper h = new Helper(action);
 
            return Task.Run(() =>
            {
                tasks.Enqueue(h);
                h.WaitCompleted();
            });
        }
 
        public void Start()
        {
            ThreadPool.QueueUserWorkItem(WorkerThread);
        }
 
        private void WorkerThread(object state)
        {
            while (true)
            {
                if (tasks.Count > 0)
                {
                    var task = tasks.Dequeue();
 
                    try
                    {
                        task.Execute();
                    }
                    finally
                    {
                        task.Complete();
                    }
                }
                else
                {
                    Thread.Sleep(250);
                }
            }
        }
 
        private class Helper
        {
            ManualResetEvent waitHandle = new ManualResetEvent(false);
            private readonly Action action;
 
            public Helper(Action action)
            {
                this.action = action;
            }
 
            public void Execute()
            {
                action();
            }
 
            public void WaitCompleted()
            {
                waitHandle.WaitOne();
            }
 
            public void Complete()
            {
                waitHandle.Set();
            }
        }
 
    }
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.03.2016, 20:06
Ответы с готовыми решениями:

Как правильно использовать async await
Здравствуйте! Есть программа, где вывод должен осуществляться при каждой итерации цикла, но этого не происходит. Весь результат выводится...

Async/ await как правильно ввести данные в async метод (консоль)
Привет , кто то может помочь ?) проблема в тому что у меня есть async метод который запускается из Main, по среди этого метода...

Async/await. Как сделать метод асинхронным?
Есть метод, который получает html private static string GetHtml(string id) { using (var client = new...

9
Эксперт .NET
 Аватар для kolorotur
17810 / 12961 / 3381
Регистрация: 17.09.2011
Сообщений: 21,250
20.03.2016, 10:44
Цитата Сообщение от m0nax Посмотреть сообщение
есть ли красивый и правильный путь как прикрутить async+await?
А в каком месте он должен быть прикручен?

Цитата Сообщение от m0nax Посмотреть сообщение
смысл возни - хочу контролировать потоки, например сделать 1 поток для обращений к базе, или 3 потока для обработки чего-нибудь-полезного, вот именно 3 конкретных потока, а не task.Run
Тогда работайте с потоками напрямую или через TPL.
async/await — это про разбиение задачи на неблокирующие куски, а не про потоки.
0
Эксперт .NET
 Аватар для insite2012
5546 / 4309 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
20.03.2016, 12:30
m0nax, если еще не читали, прочитайте в книге Албахари главу 14, там как раз рассматриваются вопросы, связанные с async-await. Но как выше верно сказано, ваша задача вряд ли решится с их применением.
Если просто, то рассмотрим такой вариант. К примеру, есть группа методов, некоторые из которых являются блокирующими. Нам надо их выполнить все. В классическом варианте, чтобы не повесить внешний код, нам их все придется запустить в отдельном потоке, даже если какие-то из них и не блокируют вызывающий код (выполняются быстро). А применение async-await позволяют, во-первых, запустить каждый из этих вызовов по отдельности, освобождая вызывающий поток после каждого вызова, и во вторых, позволяют получить результат (с возвратом в точку, где данный метод был вызван). Как аналог-использование итераторов. Там тоже механизм в чем-то похож. Если по терминологии Албахари, то Thread, Task - крупномодульный параллелизм, а async-await-мелкомодульный.
0
 Аватар для Anklav
447 / 305 / 47
Регистрация: 23.01.2013
Сообщений: 661
20.03.2016, 14:18
Тот вариант который есть у вас не потокобезопасный, очередь редактируется из нескольких потоков.
Во вторых не рекомендуется поток пула забирать навсегда. Если вам нужен отдельный поток на все время жизни приложения - создайте его.

Реализация очереди которая использует ThreadPool только если есть работа.
Если работы нету, поток будет отпущен обратно в пул, до того момента пока он опять не понадобится.
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
  public abstract class TaskQueue : IDisposable
  {
    private readonly object syncObject = new object();
    private readonly Queue<Action> commands = new Queue<Action>();
    private volatile bool inProcess;
 
    private static readonly TimeSpan disposeEventTimeout = TimeSpan.FromSeconds(10);
    private readonly ManualResetEvent disposeEvent = new ManualResetEvent(true);
    private bool disposed;
 
    public void Enqueue(Action action)
    {
      lock (syncObject)
      {
        commands.Enqueue(action);
        if (!inProcess)
        {
          inProcess = true;
          disposeEvent.Reset();
          ThreadPool.QueueUserWorkItem(Process);
        }
      }
    }
 
    private void Process(object o)
    {
      while (true)
      {
        Action action;
 
        lock (syncObject)
        {
          if (commands.Count == 0)
          {
            inProcess = false;
            disposeEvent.Set();
            return;
          }
 
          action = commands.Dequeue();
        }
 
        try
        {
          action();
        }
        catch (Exception e)
        {
          OnError(e);
        }
      }
    }
 
    public void Dispose()
    {
      if (disposed)
        return;
 
      disposed = true;
 
      // Можно не очищать, если нужно дожидатся пока все задачи будут выполнены
      lock (syncObject) 
        commands.Clear();
 
      if (!disposeEvent.WaitOne(disposeEventTimeout))
        OnError(new Exception("RequestQueue.Dispose() timeout"));
    }
 
    protected abstract void OnError(Exception e);
  }
0
 Аватар для m0nax
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
20.03.2016, 15:29  [ТС]
insite2012, не понимаю все эти рассуждения про разницу task и asynс, в 95% случаев это одно целое и совершенно не резделимо
я знаю всего два случая когда async != отдельный поток - сокеты и файлы, это зашито в ядре ОС через некий overlapped IO на уровне прерываний
все остальные миллион вариантов использования async это _всегда_ отдельный поток, известный как Task.Run
чтоб "освободить вызывающий поток" надо передать задачу другому потоку, либо упомянутые 2 исключения

Добавлено через 5 минут
ну а по теме - я понял что система тасков совершенно не гнется и не расширяется, либо как есть, либо никак

Anklav спасибо конечно за труды, но это был код просто для наглядности накиданный за 3 минуты, а не рабочий вариант )
0
 Аватар для Anklav
447 / 305 / 47
Регистрация: 23.01.2013
Сообщений: 661
20.03.2016, 15:44
m0nax, написав пример я отталкивался этих слов:
Цитата Сообщение от m0nax Посмотреть сообщение
совершенно бессмысленный поток только ради ожидания
0
Эксперт .NET
 Аватар для insite2012
5546 / 4309 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
20.03.2016, 16:44
Цитата Сообщение от m0nax Посмотреть сообщение
не понимаю все эти рассуждения про разницу task и asynс, в 95% случаев это одно целое и совершенно не резделимо
Разница там есть. Даже не разница, а понимание того, что дают эти ключевые слова.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.03.2016, 17:46
insite2012, async await это просто удобная обертка для ContinueWith, чтобы не было labma hell'а. Не больше не меньше. Никаких разных "уровней абстракций" там нет.

Цитата Сообщение от m0nax Посмотреть сообщение
смысл возни - хочу контролировать потоки, например сделать 1 поток для обращений к базе, или 3 потока для обработки чего-нибудь-полезного, вот именно 3 конкретных потока, а не task.Run
Ну делай 3 потока, в чем проблема?
0
Warrior
 Аватар для _exp10der_
500 / 427 / 177
Регистрация: 23.11.2014
Сообщений: 932
20.03.2016, 20:06
Берите BlockingCollection https://msdn.microsoft.com/ru-... 10%29.aspx
параметризируйте типом Action/Task/TaskCompletionSource
Добавляем свои задачи Add(T)
Создаем через фабрику сколько нужно потоков и вызываем в форыче у всех GetConsumingEnumerable()
Если нужен совой заумный порядок который достает задачи есть коструктор который принимает IProducerConsumerCollection<T>
2
Master of Orion
Эксперт .NET
 Аватар для Psilon
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
21.03.2016, 12:10
m0nax, как насчет BufferBlock<int>?
C# Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static BufferBlock<int> m_data =;private static async Task ConsumerAsync()
{
    while(true)
    {
        int nextItem = await m_data.ReceiveAsync();
        ProcessNextItem(nextItem);
    }
}private static void Produce(int data)
{
    m_data.Post(data);
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.03.2016, 12:10
Помогаю со студенческими работами здесь

Как правильно настроить async await
private async void открытьToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog OpenFile = new...

Socket.Send + Async & Await: свой асинхронный метод отправки данных
Привет. Хочу написать свой асинх. метод для отправки данных при помощи класса Socket и его метода Send. Работать должно так. Есть некий...

Как использовать async и await
Почему-то async и await не ни в какую не хотят работать... Ошибка CS1061 'Task&lt;string&gt;&quot; не содержит определения для...

Как работает async await?
Не могу понять как все же отрабатывает async await. Насколько я понимаю их работу сначала должен отрабоать &quot;Запуск асинхронной...

async/await как замена многопоточности
Можно ли использовать эту конструкцию как полную замену потокам, или в каких случаях не получится?


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Обмен данными в микросервисной архитектуре
ArchitectMsa 06.04.2025
Когда разработчики начинают погружаться в мир микросервисов, они часто сталкиваются с парадоксальным правилом: "два сервиса не должны делить один источник данных". Эта мантра звучит повсюду в. . .
PostgreSQL в Kubernetes: Автоматизация обслуживания с CNPG
Mr. Docker 06.04.2025
Администраторы баз данных сталкиваются с целым рядом проблем при обслуживании PostgreSQL в Kubernetes: как обеспечить правильную репликацию данных, как настроить автоматическое переключение при. . .
Async/await в TypeScript
run.dev 06.04.2025
Асинхронное программирование — это подход к разработке программного обеспечения, при котором операции выполняются независимо друг от друга. В отличие от синхронного выполнения, где каждая последующая. . .
Многопоточность в C#: Синхронизация потоков
UnmanagedCoder 06.04.2025
Многопоточное программирование стало неотъемлемой частью разработки современных приложений на C#. С появлением многоядерных процессоров возможность выполнять несколько задач параллельно значительно. . .
TypeScript: Классы и конструкторы
run.dev 06.04.2025
TypeScript, как статически типизированный язык, построенный на основе JavaScript, привнес в веб-разработку новый уровень надежности и структурированности кода. Одним из важнейших элементов этой. . .
Многопоточное программирование: Rust против C++
golander 06.04.2025
C++ существует уже несколько десятилетий и его поддержка параллелизма постепенно наращивалась со временем. Начиная с C++11, язык получил стандартную библиотеку для работы с потоками, а в последующих. . .
std::vector в C++: от основ к оптимизации производительности
NullReferenced 05.04.2025
Для многих программистов знакомство с std::vector происходит на ранних этапах изучения языка, но между базовым пониманием и подлинным мастерством лежит огромная дистанция. Контейнер std::vector. . .
Реляционная модель и правила Кодда: фундамент современных баз данных
Codd 05.04.2025
Конец 1960-х — начало 1970-х годов был периодом глубоких трансформаций в области хранения и обработки данных. На фоне растущих потребностей бизнеса и правительственных структур существовавшие на тот. . .
Асинхронные операции в Django с Celery
py-thonny 05.04.2025
Разработчики Django часто сталкиваются с проблемой, когда пользователь нажимает кнопку отправки формы и. . . ждёт. Секунды растягиваются в минуты, терпение иссякает, а интерфейс приложения замирает. . . .
Использование кэшей CPU: Максимальная производительность в Go
golander 05.04.2025
Разработчикам хорошо известно, что эффективность кода зависит не только от алгоритмов и структур данных, но и от того, насколько удачно программа взаимодействует с железом. Среди множества факторов,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
Выделить код Копировать код Сохранить код Нормальный размер Увеличенный размер