Last active
March 24, 2018 08:51
-
-
Save DvdKhl/22beb783902fa7e676ba87b2dc50cb51 to your computer and use it in GitHub Desktop.
Async/Await: Overlapping execution but only execute expensive task once per overlap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class OverlapAsyncLock { | |
public class OverlapLock : IDisposable { | |
private bool isFirst; | |
private OverlapAsyncLock owner; | |
internal OverlapLock(bool isFirst, OverlapAsyncLock owner) { | |
this.isFirst = isFirst; | |
this.owner = owner; | |
} | |
public void Dispose() { | |
if (isFirst) owner.isActive = 0; | |
owner.semaphore.Release(); | |
} | |
public bool IsFirst => isFirst; | |
} | |
private int isActive; | |
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1); | |
private readonly OverlapLock first, other; | |
public OverlapAsyncLock() { | |
first = new OverlapLock(true, this); | |
other = new OverlapLock(false, this); | |
} | |
public async Task<OverlapLock> Lock() { | |
var localIsActive = Interlocked.CompareExchange(ref isActive, 1, 0); | |
await semaphore.WaitAsync(); | |
return localIsActive == 0 ? first : other; | |
} | |
} | |
//Usage: | |
//private OverlapAsyncLock overlapAsyncLock = new OverlapAsyncLock(); | |
//... | |
//using (var overlapLock = await overlapAsyncLock.Lock()) | |
//if (overlapLock.IsFirst) { } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment