我需要能够让一个信号量的线程等待,但是当我释放它们时,没有其他线程应该再次对该信号量等待-它应该只允许任何后续线程。我找不到任何示例。
这里是一个例子。设置后,我需要允许所有对“ 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();
}
}
}
答案 0 :(得分:3)
我建议您使用ManualResetEvent。它就是为此而设计的。 在手动重置事件实例上调用WaitOne()的所有线程将被阻塞,直到通过调用Set()发出手动重置事件的信号为止。然后,释放所有阻塞的线程。
答案 1 :(得分:1)
这听起来像是您用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()