Эквивалент очередей отправки Objective C в подходе или идиоме C # .NET

2

Я новичок в мире С#.Net и создаю службу.NET API, которая записывает в таблицу базы данных MS Access, которая выполняет полные блокировки таблиц, одновременно будет записываться до 20 человек (мы избавиться от Access, но не скоро!). Мы должны обеспечить, чтобы "писатели" не блокировались.

Хотя многопотоковое решение будет работать на большинстве языков, Apple рекомендует использовать диспетчерские очереди для поддержки проблем параллелизма, таких как выше (см. Выдержку ниже), где запросы на общий ресурс помещаются в очередь и обрабатываются по одному за раз, чтобы избежать конфликтов.

Есть ли эквивалентный подход или идиома в С#?

Я действительно видел этот вопрос, но на самом деле у меня не было ответа в правильном контексте, который мне нужен.

Больше подробностей:

Выдержка из диспетчерских очередей Документы Objective-C:

Очереди отправки - это механизм на основе C для выполнения пользовательских задач. Очередь отправки выполняет задачи как последовательно, так и одновременно, но всегда в порядке ввода-вывода. (Другими словами, очередь отправки всегда деактивирует и запускает задачи в том же порядке, в котором они были добавлены в очередь.) В очереди последовательной диспетчеризации выполняется только одна задача за раз, ожидая завершения этой задачи перед тем, как выполнить деинструмент и запустить новый. Напротив, параллельная очередь отправки запускает столько задач, сколько может, не дожидаясь завершения уже начатых задач.

Очереди отправки имеют другие преимущества:

Они обеспечивают простой и простой интерфейс программирования. Они предлагают автоматическое и целостное управление пулами потоков. Они обеспечивают скорость настроенной сборки. Они намного эффективнее с точки зрения памяти (поскольку стеки потоков не задерживаются в памяти приложения). Они не попадают в ядро под нагрузкой. Асинхронная диспетчеризация задач в очереди отправки не может заблокировать очередь. Они грациозно расходятся в споре. Серийные очереди отправки предлагают более эффективную альтернативу замкам и другим примитивам синхронизации.

Задачи, которые вы отправляете в очередь отправки, должны быть инкапсулированы внутри любой функции или блочного объекта

EDIT: Оказывается, что.Net "Main Loop" или основной поток - это то, где вы можете делать запросы на обработку вашего кода. Основной цикл - это то, где обычно выполняется весь пользовательский интерфейс. В соответствии с этим вопросом SO Главный контур Windows GUI в С#... где он? Вы также можете получить доступ к нему через Application.Run и Timer

  • 1
    Поскольку в большинстве случаев гарантия последовательного порядка очередей отправки бесполезна, вы можете просто использовать пулы потоков, которые существуют практически на всех языках - они будут более эффективными для загрузки. Если вам нужна последовательная диспетчеризация, вы обычно выполняете работу с графическим интерфейсом, и в этом случае ваш фреймворк предоставляет нужный инструмент (например, диспетчеры для WPF / WinForms). В тех редких ситуациях, когда вам нужно такое поведение, простая блокирующая очередь или аналогичная система подойдет, но я бы поставил под сомнение дизайн.
  • 0
    Спасибо @Voo, позвольте мне рассмотреть эти варианты.
Теги:
multithreading
synchronization

1 ответ

2
Лучший ответ

Я нашел ваш вопрос интересным и связанным с областью.NET Framework, я мог бы использовать больше знаний, поэтому я сделал небольшое исследование по этой теме. Ну вот:

Существует несколько вариантов.NET, связанных с дружескими управляющими потоками, которые могут помочь с тем, что вы пытаетесь сделать. TaskScheduler.QueueTask являются TaskScheduler.QueueTask и ThreadPool.QueueUserWorkItem. BackgroundWorker также, возможно, применим к вашей архитектурно незавидной ситуации.

Ни в документации для TaskScheduler ни в ThreadPool задачи /TaskScheduler очереди не упоминается любая гарантия порядка заказов в очереди. Если порядок ваших многопоточных задач очень важен, основанный на моих, по общему признанию, ограниченных знаниях платформы.NET, вы можете захотеть гарантировать, что очередь выполняется с помощью стартового метода очереди, который принимает запросы на запись и записывает в базу данных или ставит в очередь запись пока права на запись не будут доступны. Это будет немного грязно, потому что вам нужно будет блокировать параллелизм. Этот github-хостинг код из аналогичного вопроса SO может быть хорошим для этого. Я его не тестировал.

В качестве альтернативы вы можете ставить в очередь задачи записи в пул потоков, ограниченный одним потоком за один раз, используя SetMaxThreads. У меня нет гарантий, что это подходит для вашей ситуации или когда-либо, хотя это кажется простым.

надеюсь, это поможет

EDIT: Дальнейшие исследования аналогичного SO-вопроса, отмеченные оригинальным вопросником, Concurrent Queue, новый с.NET 4.0, обеспечивают обработку следующей задачи из задач с ConcurrentQueue без дополнительного кода блокировки параллелизма, необходимого для обычной Queue были использованы. Такой подход позволил бы одновременно выполнять несколько задач, а не всегда, ожидая завершения предыдущей задачи, как в потоке пула потоков нитевого процессора.

  • 0
    Спасибо @ stackuser83, этот материал становится немного волосатым, поэтому я хочу посмотреть на него немного, чтобы понять, что имеет смысл.
  • 0
    Мне определенно нужна последняя победа. @ stackuser83, твоя ссылка привела меня в ConcurrentQueue, который проводит расследование !!
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню