Как в ThreadPool проверить, что все потоки завершены
От: iumag  
Дата: 05.05.16 15:37
Оценка:
Как в пуле потоков проверить, что все фоновые потоки завершены, а после этого запускать уже другую задачу?
Re: Как в ThreadPool проверить, что все потоки завершены
От: VladCore  
Дата: 05.05.16 15:54
Оценка:
Здравствуйте, iumag, Вы писали:

I>Как в пуле потоков проверить, что все фоновые потоки завершены, а после этого запускать уже другую задачу?


1
в 4-м .NET

https://msdn.microsoft.com/ru-ru/library/system.threading.barrier%28v=vs.110%29.aspx

В терминах барьера у тебя всего один стейдж

2
в старом .net надо счетчик завести незавершенных потоков задач и один ManualResetEvent
По окончании каждой задачи надо уменьшитть счетчик на еденицу и если он упал до нуля, то открываешь ManualResetEvent
Отредактировано 05.05.2016 16:04 VladCore . Предыдущая версия . Еще …
Отредактировано 05.05.2016 16:03 VladCore . Предыдущая версия .
Re: Как в ThreadPool проверить, что все потоки завершены
От: Vladek Россия Github
Дата: 05.05.16 16:04
Оценка:
Здравствуйте, iumag, Вы писали:

I>Как в пуле потоков проверить, что все фоновые потоки завершены, а после этого запускать уже другую задачу?


Решать задачу уровнем выше? Например организовать очередь заданий и по таймеру запускать параллельно выполняться N-ое количество из них.

  Простейший планировщик задач
class Job<TInput, TOutput>
{
    private readonly TInput data;
    private readonly TaskCompletionSource<TOutput> taskSource;

    public Job(TInput data)
    {
        this.data = data;
        this.taskSource = new TaskCompletionSource<TOutput>();
    }

    public Task<TOutput> Task
    {
        get
        {
            return this.taskSource.Task;
        }
    }

    public async void RunAsync()
    {
        try
        {
            var result = await DoRealJobAsync(this.data);
            this.taskSource.SetResult(result);
        }
        catch (OperationCanceledException)
        {
            this.taskSource.TrySetCanceled();
        }
        catch (Exception x)
        {
            this.taskSource.TrySetException(x);
        }
    }

    private static async Task<TOutput> DoRealJobAsync(TInput data)
    {
        await ...
        ...
        await ...
    }

}

class JobScheduler<TInput, TOutput> : IDisposable
{
    private readonly ConcurrentQueue<Job> jobQueue;
    private readonly Timer timer;
    private readonly TimeSpan runPeriod;
    private readonly int numConcurrentJobs;

    public JobScheduler(int numConcurrentJobs, TimeSpan runPeriod)
    {
        this.numConcurrentJobs = numConcurrentJobs;
        this.runPeriod = runPeriod;

        this.jobQueue = new ConcurrentQueue<Job>();
        this.timer = new Timer(RunJobs);

        this.timer.Change(TimeSpan.Zero, this.runPeriod);
    }

    public Task<TOutput> ScheduleJobAsync(TInput data)
    {
        var job = new Job<TInput, TOutput>(data);
        this.jobQueue.Enqueue(job);
        return job.Task;
    }

    public Dispose()
    {
        this.timer.Dispose();
    }

    private void RunJobs(object state)
    {
        for (var i = 0; i < this.numConcurrentJobs; ++i)
        {
            Job job;
            if (this.jobQueue.TryDequeue(out job))
                job.RunAsync();
        }
    }
}
Отредактировано 05.05.2016 16:06 Vladek . Предыдущая версия .
Re: Как в ThreadPool проверить, что все потоки завершены
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 05.05.16 17:03
Оценка: +6
Здравствуйте, iumag, Вы писали:

I>Как в пуле потоков проверить, что все фоновые потоки завершены, а после этого запускать уже другую задачу?


Использовать Task/Task<T>. Там и джоиниться можно по завершению с помощью Task.WhenAll и подобных вещей. Гораздо удобнее, чем основываться на потоках пула потоков напрямую.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.