В моей программе доступ к функции должно иметь только определенное количество потоков. Есть следующий код:
int totalTasksExecute = 3, currentTasksExecute = 0;
Task[] tasks = new Task[totalTasksExecute];
foreach(ObjModel obj in Objs)
{
if (currentTasksExecute == totalTasksExecute)
{
Task.WaitAll(tasks);
currentTasksExecute = 0;
}
Thread.Sleep(500);
tasks[currentTasksExecute++] = Task.Factory.StartNew(() => GetWebInfo(obj));
}
Task.WaitAll(tasks);
Так как он встречается несколько раз, то я решил оформить в виде отдельного класса. В классе для одновременного ограничения доступа к функции я использую Semaphore.
public class MultiTasks<T>
{
private readonly Action<T> _callback;
private readonly Semaphore semaphore;
private readonly List<T> ts;
private readonly AutoResetEvent[] waitHandles;
private int Count;
public MultiTasks(Action<T> callback, int maxRunTasks, List<T> objListForTask)
{
ts = objListForTask;
_callback = callback;
semaphore = new Semaphore(maxRunTasks, maxRunTasks);
waitHandles = new AutoResetEvent[objListForTask.Count];
for (int i = 0; i < waitHandles.Length; i++)
waitHandles[i] = new AutoResetEvent(false);
}
public void Start(int waitMilliSeconds)
{
Count = 0;
foreach(T obj in ts)
Task.Factory.StartNew(() =>
{
semaphore.WaitOne();
_callback(obj);
waitHandles[Count].Set();
Interlocked.Increment(ref Count);
Thread.Sleep(waitMilliSeconds);
semaphore.Release();
});
WaitHandle.WaitAll(waitHandles);
}
}
Вызываю таким образом:
MultiTasks<ObjModel> multiTasks =
new MultiTasks<ObjModel>(GetWebInfo, 3, objs.ToList());
multiTasks.Start(500);
Вопрос в том, что в первом случае время обработки занимает около 30 сек, то во втором случае в 2 раза больше. Может быть класс не правильно реализовал? Или не правильно использую Semaphore?
Если вы делаете что то, что должно работать параллельно, но не более N потоков одновременно, может, имеет смысл пользоваться готовыми конструкциями? Как пример:
int i = 0;
Enumerable.Range(1, 100).AsParallel().WithDegreeOfParallelism(3).ForAll(x =>
{
Interlocked.Increment(ref i);
Console.WriteLine($"Processing {x} - threads there - {i}");
Interlocked.Decrement(ref i);
});
Вывод будет что то типа
Processing 1 - threads there - 1
Processing 2 - threads there - 1
Processing 4 - threads there - 3
Processing 6 - threads there - 3
Processing 7 - threads there - 3
Processing 8 - threads there - 3
Processing 9 - threads there - 3
.........
Processing 93 - threads there - 3
Processing 94 - threads there - 3
Processing 95 - threads there - 3
Processing 96 - threads there - 3
Processing 97 - threads there - 3
Processing 98 - threads there - 3
Processing 99 - threads there - 3
Processing 100 - threads there - 3
Processing 19 - threads there - 3
Processing 20 - threads there - 2
Processing 5 - threads there - 3
То есть не более 3 одновременно запущенных потока.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Хочу выводить нажатые клавиши пользователем, в том числе сочетанияПробовал разные Key Lisener/Hook (они работают по одному и тому же принципу), но везде...
Как сделал выборку листов при импорте из Excel файла в бд laravelНа данный момент мой импорт:
Например, когда я пишу так: $users = $this->getDoctrine()->getRepository('ProfileBundle:User')->findBy(['deletedAt' => null]); то к модели пользователя подтягиваются все связанные...