Как разрешить всем последующим потокам проходить через «ворота» - PullRequest
0 голосов
/ 13 ноября 2018

Мне нужно иметь возможность заставить число потоков ожидать на семафоре, но когда я освобождаю их, никакой другой поток не должен снова ждать на этом семафоре - он должен просто разрешать любые последующие потоки. Я не могу найти никаких примеров этого.

Вот пример. Мне нужно разрешить все чтения свойства "Result" после его установки (а не только одно чтение).

private class TaskResultWrapper<T>
    {
        private T result;

        private SemaphoreSlim valueSetSemaphore = new SemaphoreSlim(0, 1);
        private CancellationToken cancellationToken;

        public TaskResultWrapper(CancellationToken cancellationToken)
        {
            this.cancellationToken = cancellationToken;
        }

        public T Result
        {
            get {
                valueSetSemaphore.Wait(cancellationToken);
                return result;
            }

            set
            {
                result = value;
                valueSetSemaphore.Release();
            }
        }
    }

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Я предлагаю вам использовать ManualResetEvent .Он предназначен только для этого.Все потоки, которые вызывают WaitOne () в экземпляре события ручного сброса, будут заблокированы, пока событие ручного сброса не будет сигнализировано вызовом Set ().Затем все заблокированные темы освобождаются.

0 голосов
/ 13 ноября 2018

Звучит так, будто вы заново изобретаете колесо с вашим TaskResultWrapper.Похоже, вы могли бы использовать TaskCompletionSource для этого.

Обратите внимание, что это также поддерживает отмену.Вот пример:

using System;
using System.Threading.Tasks;

namespace ConsoleApp10
{
    class Program
    {
        static void Main()
        {
            var test = new TaskCompletionSource<int>();

            Task.Run(() => Parallel.Invoke(
                () => printValue(test.Task),
                () => printValue(test.Task),
                () => printValue(test.Task)));

            Console.WriteLine("Tasks are all waiting on the value; press return to continue.");
            Console.ReadLine();

            test.SetResult(42); // Or test.SetCanceled() to cancel it.

            Console.WriteLine("Set result to 42 (or cancelled)");
            Console.ReadLine();
        }

        static void printValue(Task<int> task)
        {
            try
            {
                Console.WriteLine(task.Result);
            }

            catch (Exception exception)
            {
                Console.WriteLine("Task received exception: " + exception.InnerException.Message);
            }
        }
    }
}

Попробуйте запустить все как есть, а затем попробуйте после изменения test.SetResult(42) на test.SetCanceled()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...