Параллельное управление задачами в .NETC#

Место общения программистов C#
Ответить
Anonymous
 Параллельное управление задачами в .NET

Сообщение Anonymous »

Мне нужно управлять многими запущенными задачами, используя коллекцию для временного хранения задач. Мне бы не хотелось получить ситуацию с "бесконечно" растущей коллекцией задач, где большая часть задач уже выполнена! Завершенная задача должна быть немедленно удалена из этой коллекции.
В финальной точке я хочу «Подождать все» невыполненные задачи, прежде чем продолжить другой код.
Это все, что я хочу. И я ищу готовый шаблон для этого!
" while (..) { Task.Start(); Tasks.Add(task); } Task.WaitAll(tasks);" (выполненная задача самостоятельно удаляется из задач)
Это мой первый пост с вопросом по «stackoverflow» — прошу прощения, если что-то не так ;-)
var TaksBag = new ConcurrentDictionary(); //I don’t know another standard solution for this collection

//some cyclic code begin
while (true) //For example, let be - an infinite loop
{

//First realization begin
Task tsk = null;
tsk = new Task(() => { var t = tsk; TasksBag.TryAdd(t, 0); SomeProcess(); TasksBag.TryRemove(t, out _); }); //Many “times” (points) in code
tsk.Start();
//First realization end

//or

//Perhaps this second realization is better begin
Task tsk = new Task(() => SomeProcess());
TasksBag.TryAdd(tsk, 0);
tsk.ContinueWith((t) => TasksBag.TryRemove(t, out _), TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.OnlyOnRanToCompletion);
tsk.Start();
//Perhaps this second realization is better end

}
//some cyclic code end

//Final point
var ta = TasksBag.Keys.ToArray();
Task.WaitAll(ta);
foreach (var tsk in ta)
TasksBag.TryRemove(tsk, out _);
//no exception processing for simplify; not needed if only hit once to this point (GC or app exit solve this)


Существует ли какой-либо установленный код шаблона для следующей конструкции (для простоты я опускаю шаблон отмены).
Могут быть две различные архитектурные ситуации в Финальной точке:
  • Новые задачи в коллекцию не добавляются. И эта точка наступает только один раз
    или
  • Новые задачи можно продолжать добавлять в коллекцию, но на этом этапе их следует исключить из коллекции. Возможно, позже в этом месте еще будет новый хит и следующая обработка "WaitAll"
Есть ли какое-то общепринятое решение такой проблемы? Или просто этот код?
Обновление №1:
Подумав, я решаю — эту проблему нельзя оставлять без обработки исключений. И это усложняет проблему после «WaitAll». Задачи, "не дошедшие до конца", останутся в коллекции задач из-за исключения (но, судя по всему, не в версии с "ContinueWith", но это хитро - исключение может произойти внутри "ContinueWith" без удаления задачи из коллекции). коллекция; "еще один вопрос" - изменится ли что-то при обработке исключений в "Конечной точке" - это рассматривать не буду) - и выполненная (неудачная) задача не удалит себя из коллекции задач!
var ta = TasksBag.Keys.ToArray();
Task.WaitAll(ta);
foreach (var tsk in ta)
TasksBag.TryRemove(tsk, out _); //no exception processing for simplify; not needed if only hit once to this point (GC or app exit solve this)

Кроме того, текст и код вопроса были скорректированы.
Обновление №2. Это действительно моя проблема:
Я парсю WEB адреса. И я хочу создать каждую задачу для обработки каждого из них. Но я задал вопрос - найти общепринятую закономерность решения проблемы ожидания еще невыполненных задач (после выхода из блока их генерации). Когда процесс может сгенерировать колоссальное количество (коротких) задач до того, как «WaitAll» будет выполнен!
Также форматирован код
Обновление 3 :
Я думаю, это
//First realization begin
Task tsk = null;
tsk = new Task(() => { var t = tsk; TasksBag.TryAdd(t, 0); SomeProcess(); TasksBag.TryRemove(t, out _); }); //Many “times” (points) in code
tsk.Start();
//First realization end

Здесь потенциально большая ошибка
"var t = tsk;"
Если я создам много задач, которые не успеют быстро выполнить. Тогда они будут поставлены в очередь перед началом старта. И что будет в переменной «tsk» к моменту начала выполнения? Будет "чужая" задача!!!
Поэтому очень неправильно так писать. А прямого способа получить ссылку на текущую задачу я не знаю. Правда, здесь есть некоторые решения (и мне кажется, что там «лучшее решение» имеет ту же проблему, которую я определил).
Но... конечно, в моем случае , сложившуюся проблему можно как-то решить
var tsk = new Task(() => { var t = TasksBag.Keys.FirstOrDefault(ts => ts.Id == Task.CurrentId); SomeProcess(u); if (t is not null) TasksBag.TryRemove(t, out _); });
TasksBag.TryAdd(tsk, 0);
tsk.Start();


Подробнее здесь: https://stackoverflow.com/questions/792 ... ent-in-net
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»