-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #137 from icarus-consulting/i136-use-strong-named-…
…references Use strong named references
- Loading branch information
Showing
174 changed files
with
14,906 additions
and
23 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[*.cs] | ||
|
||
# CA1068: CancellationToken parameters must come last | ||
dotnet_diagnostic.CA1068.severity = silent |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Contributing to AsyncEx | ||
|
||
:+1: Thanks for taking the time to contribute! :+1: | ||
|
||
If you have encountered a bug (or just have a question on how to use the library), feel free to open an issue immediately. If reporting a bug, please include the version of AsyncEx you are using, your runtime platform and version, and code to reproduce the problem. | ||
|
||
If you have an idea for code, or would like to contribute some code, the first step is to review the [design guidelines](doc/design.md). If your code falls within those guidelines, the next step is to open an issue for discussion. Finally, if the idea has been discussed and sounds like a good fit for AsyncEx, feel free to open a pull request. I know this is slow and annoying, but it makes me sad to close PRs that people put a lot of work into but don't fit in well with AsyncEx. | ||
|
||
Our code of conduct is: be nice. Seriously, I don't think we need lawyer language. Just be nice. :blush: | ||
|
||
That's it! Thanks again for contributing! :+1: |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2014 StephenCleary | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 16 | ||
VisualStudioVersion = 16.0.30517.126 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{FBBB0AFC-0473-47AC-A5F8-235524DF8A8A}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nito.AsyncEx.Tasks", "src\Nito.AsyncEx.Tasks\Nito.AsyncEx.Tasks.csproj", "{3817C77D-0C9D-4B57-8C00-27C7BC398E61}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nito.AsyncEx.Coordination", "src\Nito.AsyncEx.Coordination\Nito.AsyncEx.Coordination.csproj", "{8C44A01D-60CD-4221-A94B-86EF177D9061}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nito.AsyncEx.Interop.WaitHandles", "src\Nito.AsyncEx.Interop.WaitHandles\Nito.AsyncEx.Interop.WaitHandles.csproj", "{B48EF95C-B838-453D-8F3D-3B12F948C29E}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nito.AsyncEx.Oop", "src\Nito.AsyncEx.Oop\Nito.AsyncEx.Oop.csproj", "{47B3CBF6-BF03-4AD0-8795-4060A8AE0959}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nito.AsyncEx.Context", "src\Nito.AsyncEx.Context\Nito.AsyncEx.Context.csproj", "{C3193836-09A1-401D-A232-CC4A7431C2B4}" | ||
EndProject | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{89C049C2-1211-4BB8-A2FA-D8ECB60676A1}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncEx.Context.UnitTests", "test\AsyncEx.Context.UnitTests\AsyncEx.Context.UnitTests.csproj", "{12786A78-4A97-487A-BFB7-E79123460E61}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncEx.Coordination.UnitTests", "test\AsyncEx.Coordination.UnitTests\AsyncEx.Coordination.UnitTests.csproj", "{E8CADD51-1B46-439E-801C-83656181B8A7}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncEx.Interop.WaitHandles.UnitTests", "test\AsyncEx.Interop.WaitHandles.UnitTests\AsyncEx.Interop.WaitHandles.UnitTests.csproj", "{8EF01C49-665F-481A-AF19-1335292BE59A}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncEx.Oop.UnitTests", "test\AsyncEx.Oop.UnitTests\AsyncEx.Oop.UnitTests.csproj", "{F85ECD63-74E0-49EA-910F-0A27A915FDA2}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncEx.Tasks.UnitTests", "test\AsyncEx.Tasks.UnitTests\AsyncEx.Tasks.UnitTests.csproj", "{8B6341C7-AF1F-4713-B7C9-D097B2378142}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nito.AsyncEx", "src\Nito.AsyncEx\Nito.AsyncEx.csproj", "{EC1B4E56-E379-44BE-8662-77C1CB9E773A}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{3817C77D-0C9D-4B57-8C00-27C7BC398E61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{3817C77D-0C9D-4B57-8C00-27C7BC398E61}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{3817C77D-0C9D-4B57-8C00-27C7BC398E61}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{3817C77D-0C9D-4B57-8C00-27C7BC398E61}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{8C44A01D-60CD-4221-A94B-86EF177D9061}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{8C44A01D-60CD-4221-A94B-86EF177D9061}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{8C44A01D-60CD-4221-A94B-86EF177D9061}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{8C44A01D-60CD-4221-A94B-86EF177D9061}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{B48EF95C-B838-453D-8F3D-3B12F948C29E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{B48EF95C-B838-453D-8F3D-3B12F948C29E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{B48EF95C-B838-453D-8F3D-3B12F948C29E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{B48EF95C-B838-453D-8F3D-3B12F948C29E}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{47B3CBF6-BF03-4AD0-8795-4060A8AE0959}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{47B3CBF6-BF03-4AD0-8795-4060A8AE0959}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{47B3CBF6-BF03-4AD0-8795-4060A8AE0959}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{47B3CBF6-BF03-4AD0-8795-4060A8AE0959}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{C3193836-09A1-401D-A232-CC4A7431C2B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{C3193836-09A1-401D-A232-CC4A7431C2B4}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{C3193836-09A1-401D-A232-CC4A7431C2B4}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{C3193836-09A1-401D-A232-CC4A7431C2B4}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{12786A78-4A97-487A-BFB7-E79123460E61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{12786A78-4A97-487A-BFB7-E79123460E61}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{12786A78-4A97-487A-BFB7-E79123460E61}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{12786A78-4A97-487A-BFB7-E79123460E61}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{E8CADD51-1B46-439E-801C-83656181B8A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{E8CADD51-1B46-439E-801C-83656181B8A7}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{E8CADD51-1B46-439E-801C-83656181B8A7}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{E8CADD51-1B46-439E-801C-83656181B8A7}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{8EF01C49-665F-481A-AF19-1335292BE59A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{8EF01C49-665F-481A-AF19-1335292BE59A}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{8EF01C49-665F-481A-AF19-1335292BE59A}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{8EF01C49-665F-481A-AF19-1335292BE59A}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{F85ECD63-74E0-49EA-910F-0A27A915FDA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{F85ECD63-74E0-49EA-910F-0A27A915FDA2}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{F85ECD63-74E0-49EA-910F-0A27A915FDA2}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{F85ECD63-74E0-49EA-910F-0A27A915FDA2}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{8B6341C7-AF1F-4713-B7C9-D097B2378142}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{8B6341C7-AF1F-4713-B7C9-D097B2378142}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{8B6341C7-AF1F-4713-B7C9-D097B2378142}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{8B6341C7-AF1F-4713-B7C9-D097B2378142}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{EC1B4E56-E379-44BE-8662-77C1CB9E773A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{EC1B4E56-E379-44BE-8662-77C1CB9E773A}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{EC1B4E56-E379-44BE-8662-77C1CB9E773A}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{EC1B4E56-E379-44BE-8662-77C1CB9E773A}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(NestedProjects) = preSolution | ||
{3817C77D-0C9D-4B57-8C00-27C7BC398E61} = {FBBB0AFC-0473-47AC-A5F8-235524DF8A8A} | ||
{8C44A01D-60CD-4221-A94B-86EF177D9061} = {FBBB0AFC-0473-47AC-A5F8-235524DF8A8A} | ||
{B48EF95C-B838-453D-8F3D-3B12F948C29E} = {FBBB0AFC-0473-47AC-A5F8-235524DF8A8A} | ||
{47B3CBF6-BF03-4AD0-8795-4060A8AE0959} = {FBBB0AFC-0473-47AC-A5F8-235524DF8A8A} | ||
{C3193836-09A1-401D-A232-CC4A7431C2B4} = {FBBB0AFC-0473-47AC-A5F8-235524DF8A8A} | ||
{12786A78-4A97-487A-BFB7-E79123460E61} = {89C049C2-1211-4BB8-A2FA-D8ECB60676A1} | ||
{E8CADD51-1B46-439E-801C-83656181B8A7} = {89C049C2-1211-4BB8-A2FA-D8ECB60676A1} | ||
{8EF01C49-665F-481A-AF19-1335292BE59A} = {89C049C2-1211-4BB8-A2FA-D8ECB60676A1} | ||
{F85ECD63-74E0-49EA-910F-0A27A915FDA2} = {89C049C2-1211-4BB8-A2FA-D8ECB60676A1} | ||
{8B6341C7-AF1F-4713-B7C9-D097B2378142} = {89C049C2-1211-4BB8-A2FA-D8ECB60676A1} | ||
{EC1B4E56-E379-44BE-8662-77C1CB9E773A} = {FBBB0AFC-0473-47AC-A5F8-235524DF8A8A} | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {B4638CC6-F431-4430-8FD0-C51DF9E9B77F} | ||
EndGlobalSection | ||
EndGlobal |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
 | ||
|
||
# AsyncEx | ||
|
||
A helper library for async/await. | ||
|
||
Note: This README is for AsyncEx v5 (the current version). For AsyncEx v4, see [here](https://github.com/StephenCleary/AsyncEx/tree/v4). | ||
|
||
Supports `netstandard1.3` (including .NET 4.6, .NET Core 1.0, Xamarin.iOS 10, Xamarin.Android 7, Mono 4.6, and Universal Windows 10). | ||
|
||
[](https://www.nuget.org/packages/Nito.AsyncEx/) [](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) [](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) [](https://coveralls.io/github/StephenCleary/AsyncEx?branch=master) [](https://ci.appveyor.com/project/StephenCleary/asyncex/branch/master) | ||
|
||
[](http://dotnetapis.com/pkg/Nito.AsyncEx) | ||
|
||
[Overview](doc/Home.md) - [Upgrade Guide](doc/upgrade.md) | ||
|
||
## Getting Started | ||
|
||
Install the [NuGet package](http://www.nuget.org/packages/Nito.AsyncEx). | ||
|
||
## AsyncLock | ||
|
||
A lot of developers start using this library for `AsyncLock`, an async-compatible mutual exclusion mechanism. Using `AsyncLock` is straightforward: | ||
|
||
```C# | ||
private readonly AsyncLock _mutex = new AsyncLock(); | ||
public async Task UseLockAsync() | ||
{ | ||
// AsyncLock can be locked asynchronously | ||
using (await _mutex.LockAsync()) | ||
{ | ||
// It's safe to await while the lock is held | ||
await Task.Delay(TimeSpan.FromSeconds(1)); | ||
} | ||
} | ||
``` | ||
|
||
`AsyncLock` also fully supports cancellation: | ||
|
||
```C# | ||
public async Task UseLockAsync() | ||
{ | ||
// Attempt to take the lock only for 2 seconds. | ||
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2)); | ||
|
||
// If the lock isn't available after 2 seconds, this will | ||
// raise OperationCanceledException. | ||
using (await _mutex.LockAsync(cts.Token)) | ||
{ | ||
await Task.Delay(TimeSpan.FromSeconds(1)); | ||
} | ||
} | ||
``` | ||
|
||
`AsyncLock` also has a synchronous API. This permits some threads to acquire the lock asynchronously while other threads acquire the lock synchronously (blocking the thread). | ||
|
||
```C# | ||
public async Task UseLockAsync() | ||
{ | ||
using (await _mutex.LockAsync()) | ||
{ | ||
await Task.Delay(TimeSpan.FromSeconds(1)); | ||
} | ||
} | ||
|
||
public void UseLock() | ||
{ | ||
using (_mutex.Lock()) | ||
{ | ||
Thread.Sleep(TimeSpan.FromSeconds(1)); | ||
} | ||
} | ||
``` | ||
|
||
## Other Coordination Primitives | ||
|
||
`AsyncLock` is just the beginning. The AsyncEx library contains a full suite of coordination primitives: `AsyncManualResetEvent`, `AsyncAutoResetEvent`, `AsyncConditionVariable`, `AsyncMonitor`, `AsyncSemaphore`, `AsyncCountdownEvent`, and `AsyncReaderWriterLock`. | ||
|
||
## More Stuff | ||
|
||
There's quite a few other helpful types; see [the docs for full details](doc) | ||
|
||
## Infrequently Asked Questions | ||
|
||
### Older Platforms | ||
|
||
[AsyncEx v4](https://github.com/StephenCleary/AsyncEx/tree/v4) supported .NET 4.0, Windows Store 8.1, Windows Phone Silverlight 8.0, Windows Phone Applications 8.1, and Silverlight 5.0. Support for these platforms has been dropped with AsyncEx v5. | ||
|
||
AsyncEx v3 supported Windows Store 8.0, Windows Phone Silverlight 7.5, and Silverlight 4.0. Support for these platforms has been dropped with AsyncEx v4. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## Overview | ||
|
||
The `ApmAsyncFactory` type enables easy interoperation with the Asynchronous Programming Model (APM). | ||
|
||
APM is the old-style approach to asynchronous programming that used `Begin`/`End` method pairs with `IAsyncResult` representing the asynchronous operation. The `FromApm` methods on `ApmAsyncFactory` convert from APM to TAP, and the `ToBegin` and `ToEnd` methods convert from TAP to APM. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
## Overview | ||
|
||
This is the `async`-ready equivalent of [AutoResetEvent](https://docs.microsoft.com/en-us/dotnet/api/system.threading.autoresetevent), similar to Stephen Toub's [AsyncAutoResetEvent](https://blogs.msdn.microsoft.com/pfxteam/2012/02/11/building-async-coordination-primitives-part-2-asyncautoresetevent/). | ||
|
||
Like other "events", an `AsyncAutoResetEvent` is either **set** or **unset** at any time. An `AsyncAutoResetEvent` can be changed from **unset** to **set** by calling its `Set` method. When a `WaitAsync` operation completes, the `AsyncAutoResetEvent` is automatically changed back to the **unset** state. | ||
|
||
Moving an `AsyncAutoResetEvent` to the **set** state can only satisfy a single waiter. If there are multiple waiters when `Set` is called, only one will be released. (If this is not the behavior you want, use [AsyncManualResetEvent](AsyncManualResetEvent.md) instead). | ||
|
||
When an `AsyncAutoResetEvent` is in the **set** state (with no waiters), `Set` is a noop. The `AsyncAutoResetEvent` will not remember how many times `Set` is called; those extra signals are "lost". (If this is not the behavior you want, use [AsyncSemaphore](AsyncSemaphore.md) instead). | ||
|
||
The task returned from `WaitAsync` will enter the `Completed` state when the wait is satisfied and the `AsyncAutoResetEvent` has been automatically reset. That same task will enter the `Canceled` state if the `CancellationToken` is signaled before the wait is satisfied; in that case, the `AsyncAutoResetEvent` has not been automatically reset. | ||
|
||
## Advanced Usage | ||
|
||
You can call `WaitAsync` with an [already-cancelled `CancellationToken`](Cancellation.md) to attempt to acquire the `AsyncAutoResetEvent` immediately without actually entering the wait queue. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## Overview | ||
|
||
An `AsyncCollection` is an `async`-compatible wrapper around [IProducerConsumerCollection](https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.iproducerconsumercollection-1) collections such as [ConcurrentQueue](https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentqueue-1) or [ConcurrentBag](https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentbag-1). | ||
|
||
This makes `AsyncCollection` an `async` near-equivalent of [BlockingCollection](https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.blockingcollection-1), which is a blocking wrapper around [IProducerConsumerCollection](https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.iproducerconsumercollection-1). |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
## Overview | ||
|
||
This is an `async`-ready [condition variable](https://en.wikipedia.org/wiki/Condition_variable), a classical synchronization primitive in computer science without a direct .NET equivalent. | ||
|
||
An `AsyncConditionVariable` is associated with a single [AsyncLock](AsyncLock.md). All methods on the `AsyncConditionVariable` type ***require*** that you hold the associated lock before calling them. There's no runtime checks for these preconditions because there is no way to check them; you'll just have to be careful. I recommend you combine the `AsyncLock` with its associated `AsyncConditionVariable` instances into a higher-level custom lock/signal system. Note that the simple case of a single `AsyncLock` with a single `AsyncConditionVariable` is equivalent to [AsyncMonitor](AsyncMonitor.md). | ||
|
||
Waiting on an `AsyncConditionVariable` enables an `async` method to (asynchronously) wait for some condition to become true. While waiting, that `async` method gives up the `AsyncLock`. When the condition becomes true, another `async` method notifies the `AsyncConditionVariable`, which re-acquires the `AsyncLock` and releases the waiter. | ||
|
||
When notifying the `AsyncConditionVariable`, the notifying task may choose to release only a single waiter (`Notify`) or all waiters (`NotifyAll`). If there are no waiters, the notification is "lost"; it is not remembered by the `AsyncConditionVariable`. | ||
|
||
The task returned from `WaitAsync` will enter the `Completed` state when it receives a notification and re-acquires the `AsyncLock`. That same task will enter the `Canceled` state if the `CancellationToken` is signaled before the wait is satisfied; in that case, the task will wait to enter the `Canceled` state until it re-acquires the `AsyncLock`. | ||
|
||
Remember that from the time `WaitAsync` is called to the time when its returned task completes, the `AsyncLock` is _not_ held by the calling task. | ||
|
||
Note that the correct logic for condition variables is to wait in a loop until the required condition is true. This is necessary because other tasks may execute between the notification and the completion of the wait. |
Oops, something went wrong.