async Task <INode <TState, TCost> > GetNodeAsync() { //System.Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}: GetNodeAsync: 1."); await ConsumerLock.WaitAsync(); bool hasconsumerlock = true; try { Monitor.Enter(ProducerLock); while (Nodes.Count <= 0) { Monitor.Exit(ProducerLock); List <Task> MonitoredTasks = new List <Task>(WorkerTasks); if (MonitoredTasks.Count == 0) { throw new QueueExhaustedException(); } ConsumerLock.Release(); hasconsumerlock = false; await Task.WhenAny(MonitoredTasks); await ConsumerLock.WaitAsync(); hasconsumerlock = true; Monitor.Enter(ProducerLock); } var myitem = Nodes[0]; Nodes.RemoveAt(0); VisitedStates.Add(myitem.State, myitem.AccumulatedCost); Monitor.Exit(ProducerLock); return(myitem); } finally { if (hasconsumerlock) { ConsumerLock.Release(); } } }
public async Task <TRet> PerformWorkerOperationAsync <TRet>(Func <INode <TState, TCost>, Task <TRet> > acquiredoperations) { //System.Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}: Getting node."); INode <TState, TCost> myitem; await ConsumerLock.WaitAsync(); bool hasconsumerlock = true; try { Monitor.Enter(ProducerLock); while (Nodes.Count <= 0) { Monitor.Exit(ProducerLock); List <Task> MonitoredTasks = new List <Task>(WorkerTasks); if (MonitoredTasks.Count == 0) { throw new QueueExhaustedException(); } ConsumerLock.Release(); hasconsumerlock = false; await Task.WhenAny(MonitoredTasks); await ConsumerLock.WaitAsync(); hasconsumerlock = true; Monitor.Enter(ProducerLock); } myitem = Nodes[0]; Nodes.RemoveAt(0); VisitedStates.Add(myitem.State, myitem.AccumulatedCost); Monitor.Exit(ProducerLock); } catch (Exception) { if (hasconsumerlock) { ConsumerLock.Release(); } throw; } //Still has consumerlock TaskCompletionSource <int> holder = new TaskCompletionSource <int>(); async Task <TRet> Worker(INode <TState, TCost> n) { await holder.Task; return(await acquiredoperations(n)); } var t = Worker(myitem); var cleanuptask = t.ContinueWith(async x => { await ConsumerLock.WaitAsync(); WorkerTasks.Remove(x); ConsumerLock.Release(); }); WorkerTasks.Add(t); ConsumerLock.Release(); holder.SetResult(0); //release hold await cleanuptask; return(await t); }