public Task RequestOpen(LazyResourceManager requester, CancellationToken cancellationToken) { lock (LockObj) { ReferenceCount++; switch (state) { case ResourceState.Reset: state = ResourceState.Opening; return(OpenTask = OpenResource(requester, cancellationToken)); case ResourceState.Opening: return(OpenTask); case ResourceState.Open: return(Task.CompletedTask); case ResourceState.Closing: return(CloseTask.ContinueWith(t => RequestOpen(requester, cancellationToken).Wait())); } return(Task.CompletedTask); } }
public Task RequestClose(LazyResourceManager requester) { lock (LockObj) { ReferenceCount--; if (ReferenceCount == 0) { switch (state) { case ResourceState.Reset: case ResourceState.Closing: throw new Exception("Should never happen"); case ResourceState.Opening: case ResourceState.Open: { state = ResourceState.Closing; return(CloseTask = Task.Factory.StartNew(() => { try { // wait for the resource to open before close. requester.resources[ResourceNode.Resource].OpenTask?.Wait(); } catch { } Task.WaitAll(ResourceNode.WeakDependencies.Select(requester.RequestResourceClose).ToArray()); var reslog = ResourceTaskManager.GetLogSource(ResourceNode.Resource); Stopwatch timer = Stopwatch.StartNew(); try { ResourceNode.Resource.Close(); } catch (Exception e) { reslog.Error("Error while closing \"{0}\": {1}", ResourceNode.Resource.Name, e.Message); reslog.Debug(e); } reslog.Info(timer, "Resource \"{0}\" closed.", ResourceNode.Resource); Task.WaitAll(ResourceNode.StrongDependencies.Select(requester.RequestResourceClose).ToArray()); state = ResourceState.Reset; })); } } } return(Task.CompletedTask); } }
async Task OpenResource(LazyResourceManager requester, CancellationToken cancellationToken) { var node = ResourceNode; foreach (var dep in node.StrongDependencies) { if (dep == null) { continue; } await requester.RequestResourceOpen(dep, cancellationToken); } Stopwatch swatch = Stopwatch.StartNew(); try { // start a new thread to do synchronous work await Task.Factory.StartNew(node.Resource.Open); var reslog = ResourceTaskManager.GetLogSource(node.Resource); reslog.Info(swatch, "Resource \"{0}\" opened.", node.Resource); } finally { lock (LockObj) if (state == ResourceState.Opening) { state = ResourceState.Open; } } foreach (var dep in node.WeakDependencies) { if (dep == null) { continue; } await requester.RequestResourceOpen(dep, cancellationToken); } requester.ResourceOpenedCallback(node.Resource); }