public class SampleData
{
private static readonly Semaphore pool = new Semaphore(0,1);
public string Data => getFromFile();
private static string getFromFile()
{
pool.WaitOne();
var data =
File.ReadAllText("somefilepath");
pool.Release();
return data;
}
}
在 program.cs 中
var tasks = new List<Task<string>>();
for(int i=0; i<=5; i++)
{
tasks.Add(Task.Run<string>(()=>
new SampleData().Data));
}
Task.WaitAll(tasks.ToArray());
当我运行它时,它永远不会完成任务。谁能告诉我这里有什么问题?
谢谢。
答案 0 :(得分:0)
如果 getFromFile() 抛出异常,信号量将永远不会被释放并且 Task.WaitAll 将永远等待,您需要将 pool.Release() 移动到 finally 部分。这可能就是无限期等待的原因。
private static string getFromFile()
{
pool.WaitOne();
try {
var data = File.ReadAllText("somefilepath");
return data;
}
finally {
pool.Release();
}
}
}
答案 1 :(得分:0)
首先
如果这不是跨进程,您应该考虑使用 SemaphoreSlim
。
其次
关于您对 Semaphore(0,1)
的初始化。如果 initialCount
小于 maximumCount
,效果与当前线程调用 WaitOne
(maximumCount
减去 initialCount
) 次一样。
也就是说,当您在当前配置中调用 pool.WaitOne();
时,您将一直阻塞,直到有人调用 release(直接)。
例如:
private static readonly Semaphore pool = new Semaphore(0,1);
static void Main(string[] args)
{
pool.WaitOne();
Console.WriteLine("This will never get executed");
}
您可能想要:
Semaphore(1,1)
// or
SemaphoreSlim(1,1)
最后
您必须始终将这些同步原语包装在try finally
中,否则您最终会在异常时死锁 在 Release
之前被抛出。
SemaphoreSlim
await pool.WaitAsync();
try
{
// do something
}
finally
{
pool.Release();
}
或者如果你真的需要使用 Semaphore
pool.WaitOne();
try
{
// do something
}
finally
{
pool.Release();
}