У меня есть Task.Run(() => тут метод)
Как можно сделать чтобы метод выполнялся с нужным кол-во потоков ?
Или же тогда получается что задачи не нужны и оставить только Threads ?
Asked
Active
Viewed 194 times
-1
ZidoX
- 660
-
зачем? создай несколько Task – Grundy Nov 13 '22 at 13:27
-
Это как — с нужным количеством потоков? Task.Run(...) отправляет код на thread pool и там он бежит, как и любая синхронная функция, в одном потоке. Какая ваша проблема в точности? – VladD Nov 13 '22 at 13:27
-
@VlaD, а как разбить на несколько потоков? – ZidoX Nov 13 '22 at 13:28
-
1@ZidoX: Контрвопрос — а как вы планировали делать это с Thread'ами? – VladD Nov 13 '22 at 13:29
-
https://ru.stackoverflow.com/q/1303748/373567 – aepot Nov 13 '22 at 15:24
-
Правильное решение зависит от конкретной задачи, конкретных данных и конкретных требований к производительности. – aepot Nov 13 '22 at 15:30
3 Answers
3
Чтобы что то запускать с нужным количеством потоков - самый простой способ, это использовать TPL
Parallel.For(0, 10, new ParallelOptions() {MaxDegreeOfParallelism = 10 /* Нужное количесво потоков */}, (i) => {/* ваш метод */});
tym32167
- 32,857
1
public class Program
{
public static void Main()
{
Parallel.For(0, 3, new ParallelOptions() {MaxDegreeOfParallelism = 10}, (i) => {Run("хмм");}); //Взято из предыдущего комментария
ParallelLoopResult result = Parallel.ForEach<int>(new List<int>() { 1, 3, 5, 8 }, Parallels); // Перебирает коллекцию в многопотоке
Task[] tasks = new Task[3]; // Создаем массив задач
for (int i = 0; i < tasks.Length; i++) //Перебираем задачи
tasks[i] = Task.Factory.StartNew(() => Run("эмм")); //запускаем
}
static void Parallels(int n)
{
Console.WriteLine(n);
}
static void Run(string res)
{
Console.WriteLine(res);
}
Вывод: хмм хмм хмм 1 5 3 8 эмм эмм эмм
xellan
- 560
- 3
- 11
1
Более интересная реализация
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TaskRun
{
internal class JobManager : IDisposable
{
private SemaphoreSlim _semaphore;
private CancellationTokenSource _cancelToken;
public CancellationTokenSource CancellationTokenSource
{
get => _cancelToken ?? new CancellationTokenSource();
}
public async Task JobStart(List<string> list, Func<string, Task> action, int thread)
{
_semaphore = new SemaphoreSlim(thread);
_cancelToken = new CancellationTokenSource();
var pool = new List<Task>(thread);
foreach (var item in list)
{
await _semaphore.WaitAsync().ConfigureAwait(false);
pool.Add(Task.Run(() =>
{
action(item);
_semaphore.Release();
}, _cancelToken.Token));
}
await Task.WhenAll(pool.ToArray()).ConfigureAwait(false);
}
public void JobStop()
{
_cancelToken.Cancel();
}
public void Dispose()
{
_semaphore?.Dispose();
_cancelToken?.Dispose();
}
}
}
Запуск в многопотоке
JobManager _manager = new JobManager();
var Data = new List<string>(){"Один", "Два"};
await _manager.JobStart(Data, Work, 10);
//10 число потоков, Work наш метод, Data - Передаем список в метод для обработки
async Task Work(string iteam)
{
Console.Writeline(iteam);
}
xellan
- 560
- 3
- 11
-
А если у меня основной метод в void, делать
async voidнужно илиasync Task? – ZidoX Nov 13 '22 at 20:55 -
@ZidoX void не поддерживает ожидание, то есть если вы напишете await TaskMethod() это будет не правильно, тогда вам нужно изначально писать метод Task. В кратце если вам не нужны методы Task, то пишете спокойно async void, а если будет хоть один метод Task не предвиденно, вам возможно придется переделать все методы в Task – xellan Nov 13 '22 at 23:49
-
Если вы будете из примера с JobManager использовать код, то он Настроен на Task, void в нем работать не будет, чтобы передавать туда void измените public async Task JobStart(List
list, Func<string, Task> action, int thread) на public async Task JobStart(List – xellan Nov 13 '22 at 23:51list, Action action, int thread)