stephencleary / asyncex Goto Github PK
View Code? Open in Web Editor NEWA helper library for async/await.
License: MIT License
A helper library for async/await.
License: MIT License
Apologies if I'm misusing the AsyncProducerConsumerQueue<T>
, but I'd like to be able to to access the Count property of the underlying Queue<T>
so that I can tell when all my async queues are empty. Is this deliberately not surfaced in the API?
(From Andy):
Firstly - thank you so much for your very useful library.
I am developing a WinRT app and using your NotifyTaskCompletion classes.
I note that the INotifyPropertyChanged.TaskCompleted property comment says:
"This property never changes and is never null"
However, when mocking up some data using Task.FromResult I have observed INotifyPropertyChanged.TaskCompleted set to null.
In the NotifyTaskCompletionImplementation ctor I see that the TaskCompleted property is only set if (!task.IsCompleted)
Is the comment wrong and should I check Execution.IsCompleted before awaiting Execution.TaskCompleted or is this a bug?
Is there any straightforward way of using AsyncManualResetEvent.WaitAsync() with a timeout similar to WaitHandle.WaitOne(int millisecondsTimeout)?
I've been using Microsoft's TAP approach to async wait handles which can support timeouts through ThreadPool.RegisterWaitForSingleObject().
I'd prefer to use the clean AsyncManualResetEvent if possible.
Hi,
hopefully it's not a repost as I found a similar issue already stating that the problem is fixed in 3.0.1. It seems that it is not for Xamarin.Forms PCL Projects.
Build Output:
1>Exception while loading assemblies: System.IO.FileNotFoundException: Could not load assembly 'Nito.AsyncEx.Enlightenment, Version=3.0.1.0, Culture=neutral, PublicKeyToken='. Perhaps it doesn't exist in the Mono for Android profile?
1>File name: 'Nito.AsyncEx.Enlightenment.dll'
1> at Xamarin.Android.Tuner.DirectoryAssemblyResolver.Resolve(AssemblyNameReference reference, ReaderParameters parameters)
1> at Xamarin.Android.Tasks.ResolveAssemblies.AddAssemblyReferences(ICollection1 assemblies, AssemblyDefinition assembly, Boolean topLevel) 1> at Xamarin.Android.Tasks.ResolveAssemblies.AddAssemblyReferences(ICollection
1 assemblies, AssemblyDefinition assembly, Boolean topLevel)
1> at Xamarin.Android.Tasks.ResolveAssemblies.Execute()
Sir, I'm sorry I'm using a GitHub issue for something is not stricktly related to Github, anyway:
I was not able to locate any license disclaimer while I got the Package using NuGET while here on github the license (MIT) is present.
Am I blind or license under nuget is missing?
And, in case it is missing, has this a particular sense?
Thanks in advance,
Monducci Marco
Hi Stephen,
great job with the library.
Have you considered adding an option (besides cancellationToken) of Timespan timeout?
The use case would be e.g. with AsyncLock, for the stack of tasks not to build up. I would like to execute a function exactly once, the ones stacking up and waiting for the lock would be automatically dismissed after some timeout.
Consider this scenario (webapi):
private async Task<DbUserDetails> GetDetailsAsync(string userId)
{
return await _dbContext.UserDetails.FindAsync(userId);
}
private Task<DbUserDetails> GetDetails(string userId)
{
return _dbContext.UserDetails.FindAsync(userId);
}
[HttpGet]
[AllowAnonymous]
[Route("test")]
public IHttpActionResult TestGet()
{
var details = GetDetails("aeb6c2b5").WaitAndUnwrapException(); // This works
var details = GetDetailsAsync("aeb6c2b5").WaitAndUnwrapException(); // This doesn't work
return Ok(details);
}
The second case doesn't work. I think the context gets lost on any await calls inside the Task
. Do you have any idea why it happens, and how to handle this?
Regards
The following sample will result in what appears to be threadpool saturation:
for (int i = 0; i < 40; i++)
{
var manualEvent = new AsyncManualResetEvent();
Task.Run(() =>
{
Console.WriteLine("Set. Time={0}", DateTime.Now.ToString("hh:mm:ss"));
manualEvent.Set();
});
}
The output will show that the Set method is called rapidly for the first X available threads on the threadpool, and then start to slow down while the threadpool creates new threads.
On my machine, the default threadpool has 8 threads and it took 31 seconds before the last Set() could be called.
Does an async version of the Set method make sense? The following code solved my issue, but can this create any wrong side-effect that I don't see?
public Task SetAsync()
{
bool lockTaken = false;
object obj;
try
{
Monitor.Enter(obj = this._sync, ref lockTaken);
TaskShim.Run<bool>((Func<bool>)(() => this._tcs.TrySetResult()));
return @this._tcs.Task;
}
finally
{
if (lockTaken)
Monitor.Exit(obj);
}
}
Thanks for the great library by the way!
(from email):
I've hit a small issue referencing it in a Xamarin.iOS class library project. By this I mean a platform-specific assembly (in VStudio 2013, New Project/iOS/Class Library). When I build this (empty) assembly, I get the following compilation errors:
1>C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets(1697,5): warning MSB3277: Found conflicts between different versions of the same dependent assembly that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed.
1>c:\Users\mpilot\Documents\Visual Studio 2013\Projects\IosTestClassLib\packages\Microsoft.Bcl.1.1.8\lib\portable-net40+win8\System.IO.dll : error CS1703: An assembly with the same identity 'System.IO, Version=2.6.8.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' has already been imported. Try removing one of the duplicate references.
1>c:\Users\mpilot\Documents\Visual Studio 2013\Projects\IosTestClassLib\packages\Microsoft.Bcl.1.1.8\lib\portable-net40+win8\System.Runtime.dll : error CS1703: An assembly with the same identity 'System.Runtime, Version=2.6.8.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' has already been imported. Try removing one of the duplicate references.
1>c:\Users\mpilot\Documents\Visual Studio 2013\Projects\IosTestClassLib\packages\Microsoft.Bcl.1.1.8\lib\portable-net40+win8\System.Threading.Tasks.dll : error CS1703: An assembly with the same identity 'System.Threading.Tasks, Version=2.6.8.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' has already been imported. Try removing one of the duplicate references.
I believe the nuget package has no specific match for the Xamarin.iOS platform and default to .Net 4. Since Xamarin supports async natively (AFAIK), the Microsoft.Bcl package types conflict with those in Xamarin.iOS (mono). If I remove the Nito.AsyncEx nuget references and manually add the Nito.AsyncEx assemblies from the Net45 sub-folder of the nuget package, my code compiles and runs as it should.
[Same error with Nito.AsyncEx preview]:
1>C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets(1697,5): warning MSB3277: Found conflicts between different versions of the same dependent assembly that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed.
1>c:\Users\mpilot\Documents\Visual Studio 2013\Projects\IosTestClassLib\packages\Microsoft.Bcl.1.1.8\lib\portable-net40+win8\System.IO.dll : error CS1703: An assembly with the same identity 'System.IO, Version=2.6.8.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' has already been imported. Try removing one of the duplicate references.
1>c:\Users\mpilot\Documents\Visual Studio 2013\Projects\IosTestClassLib\packages\Microsoft.Bcl.1.1.8\lib\portable-net40+win8\System.Runtime.dll : error CS1703: An assembly with the same identity 'System.Runtime, Version=2.6.8.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' has already been imported. Try removing one of the duplicate references.
1>c:\Users\mpilot\Documents\Visual Studio 2013\Projects\IosTestClassLib\packages\Microsoft.Bcl.1.1.8\lib\portable-net40+win8\System.Threading.Tasks.dll : error CS1703: An assembly with the same identity 'System.Threading.Tasks, Version=2.6.8.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' has already been imported. Try removing one of the duplicate references.
Steps:
PM> Install-Package Nito.AsyncEx -Version 3.0.0
class Program
{
static void Main(string[] args)
{
AsyncContext.Run(() => MainAsync(args));
}
static async void MainAsync(string[] args)
{
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
Resharper complains about System.Runtime, but actually code runs fine unless you let resharper add that reference to runtime, then it fails to build. Interestingly, suspending and resuming resharper then does not show error.
Understand if you regard this as resharper bug, but thought that adding reference to System.Runtime 4.0.0.0 should not stop compilation with your nuget package.
Tho I know I can just download the binary from codeplex, but I think having a nuget package would help a lot.
Or is there an ActionDispatcherSynchronzationContext equivalent that I missed?
A synchronous method is needed in AsyncLock to test whether or not the lock is currently taken. For example, we may have an AsyncCommand which CanExecute only when a shared async resource is not locked. We need to test whether the lock is taken, in order to calculate CanExecute:
/// <summary>
/// Returns true iff the lock is already taken.
/// </summary>
public bool IsTaken {
get {
lock (this._mutex) {
return this._taken;
}
}
}
Ideally this property would be notified so that we can more easily call CanExecuteChanged.
Generally, it is undesired behavior to cache a Task<T>
that was completed with an exception.
AsyncLazy<T>
needs an option to control this caching behavior, in a manner similar to how LazyThreadSafetyMode
controls the caching for Lazy<T>
.
Also, consider an option to run the delegate directly rather than always on a thread pool thread. Perhaps this should be the default behavior, with users including a Task.Run
if desired?
Also see pull request 40 for reasoning behind these options.
I copy pasted the AsyncLock example and I'm getting an error message.
Cannot await 'Nito.AsyncEx.AwaitableDisposable<System.IDisposable>'
The code is:
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));
}
}
I need to reset the event, but there isn't a Reset method like the normal AutoResetEvent has. Any reason for this?
Would it be possible to add a public getter for _taken
to the AsyncLock
. I have a usecase where I have an asnyc lock in a method which should not execute a second time if it is already running, so the following would do the trick:
public async Task DoWorkAsync()
{
if (asyncLock.IsTaken)
return;
using (await asyncLock.LockAsync().ConfigureAwait(false))
{
// do work
}
}
In my case the possible race condition for the small gap between the check and the lock beeing taken does not matter as it is only a "performance penalty" if a second call gets to the lock, but maybe you could even implement some kind of TryLockAsync
which would be thread-safe without a race condition...
Hello, it will be nice to add .NET Core support
Good evening Stephen,
regarding AsyncContext's limitation of executing one task at a time - is there any (built-in) way to allow more than one task to be executed in parallel, rather than the current sequential one?
Cheers and thanks,
-Jörg
(I've also posted this as a comment at http://blog.stephencleary.com/2012/02/async-console-programs.html ..but as this post is already a bit.. old.. I though it might make more sense here)
Having support for async timer and async retry would be great too !
Hello. I'm having a strange issue with my project, and I'm not sure what is to blame - AsyncEx, TweetInvi, or me. :(
Basically, I have a working WPF app that uses TweetInvi and plenty of async - it all works fine. I recently wanted to make a console version, and found AsyncEx with its AsyncContext class, which resolves issues with using async methods with console applications. It sounded perfect. Unfortunately, my application didn't work. I've managed to shrink the issue down to these three scenarios:
Scenario 1:
This is what I'm trying to do. It doesn't work. I use TweetInvi's Sync.ExecuteTaskAsync method from within AsyncEx's AsyncContext.Run. TweetInvi's Sync.ExecuteTaskAsync never returns - I can set a breakpoint on the following line and it never triggers. This completely stops my application from progressing.
private static int Main(string[] args) {
return AsyncContext.Run(Program.MainAsyc);
}
private static async Task<int> MainAsyc() {
var twitterCredentials = new TwitterCredentials(blankedOut1, blankedOut2, blankedOut3, blankedOut4);
Auth.SetCredentials(twitterCredentials);
var latestTweets = await Sync.ExecuteTaskAsync(() => Timeline.GetUserTimeline(blankedOut5, new UserTimelineParameters {
MaximumNumberOfTweetsToRetrieve = 20,
ExcludeReplies = true
}));
return 0;
}
Scenario 2:
In this scenario, I use TweetInvi's Sync.ExecuteTaskAsync on its own in the normal Main method, without using AsyncEx at all. It works fine and returns.
private static int Main(string[] args) {
var twitterCredentials = new TwitterCredentials(blankedOut1, blankedOut2, blankedOut3, blankedOut4);
Auth.SetCredentials(twitterCredentials);
Sync.ExecuteTaskAsync(() => Timeline.GetUserTimeline(blankedOut5, new UserTimelineParameters {
MaximumNumberOfTweetsToRetrieve = 20,
ExcludeReplies = true
})).Wait();
return 0;
}
Scenario 3:
In this scenario, I use AsyncEx's AsyncContext.Run method, without using TweetInvi at all. It works fine and returns.
private static int Main(string[] args) {
AsyncContext.Run(Test);
return 0;
}
private static async Task Test() {
await Task.Run(() => Thread.Sleep(5000));
}
Why doesn't scenario 1 work? I'd really appreciate any help with this.
Is there any way to tell if a lock is actually applied when calling AsyncReaderWriterLock.ReaderLock with a already canceled CancellationToken? I don't see a way to do it. The only way I can think to do it is to change the code to return NULL if the lock wasn't actually applied. I'm happy to send a pull request but wanted to check if there was a better way of accomplishing this.
Hi Stephen - as always thanks for the tremendous contributions to the .net ecosystem.
I have one minor issue with AsyncEx discoverablility in nuget: The music bar icon has a transparent background that is impossible to make out when using the dark theme in VS. I searched for it recently and skipped passed it twice looking for the familiar music bar.
Recommended fix is adding a white background to the icon as attached.
Kind regards,
I created a unit test to try and understand how it works.. I came across a scenario that should work (reread your docs and others for a good 15 minutes).
[Fact]
public async Task WillWaitForMonitor() {
var monitor = new AsyncMonitor();
// 1. Fall through with the delay.
var sw = Stopwatch.StartNew();
using(await monitor.EnterAsync())
await Task.WhenAny(Task.Delay(100), monitor.WaitAsync()).AnyContext();
sw.Stop();
Assert.InRange(sw.ElapsedMilliseconds, 100, 125);
// 2. Wait for the pulse to be set.
sw.Restart();
using (await monitor.EnterAsync()) {
Task.Run(async () => {
await Task.Delay(50).AnyContext();
Logger.Trace().Message("Pulse").Write();
monitor.Pulse();
Logger.Trace().Message("Pulsed").Write();
});
Logger.Trace().Message("Waiting").Write();
await monitor.WaitAsync().AnyContext();
}
sw.Stop();
Assert.InRange(sw.ElapsedMilliseconds, 50, 100);
}
It outputs
[15:51:59.602 T InMemoryLockTests] Waiting
[15:51:59.654 T InMemoryLockTests] Pulse
[15:51:59.657 T InMemoryLockTests] Pulsed
But the monitor.WaitAsync() never completes and waits for ever. Is there a reason for this?
Previously we were using a BlockingCollection and it seemed to be working pretty good. I saw your recommendation to use a AsyncCollection instead. After updating however, I noticed that we get dead locks right away....
Task.Run(() => {
var subscribers = _subscribers.GetConsumingEnumerable(cancellationToken).ToList();
var messageTypeSubscribers = subscribers.Where(s => s.Type.IsAssignableFrom(messageType)).ToList();
});
I need to iterate over the subscribers, but it blocks and never returns. Recommendations?
Hi Stephen,
Thanks for your great library!
I have a simple console app that uses AsyncContext.Run(Func) to run a task. If the task throws an exception, it seems to keep retrying the task over and over again....
Am I doing something stupid?
Cheers,
Steve
class Program
{
static void Main(string[] args)
{
AsyncContext.Run(() => RunAsync());
}
static async Task RunAsync()
{
await DoSomethingAsync();
throw new Exception();
}
static async Task DoSomethingAsync()
{
await Task.Delay(1000);
}
}
Please change CLSCompliant(false) to CLSCompliant(true). This would enable me to consume the library in CLS compliant libraries. Thank you!
Hello!
I am experiencing issues with referencing latest Nito.AsyncEx in portable library.
Everything builds well until I am trying to build Xamarin.Android project which references that portable library. I am getting linker exception that Nito.AsyncEx.Enlightenment.dll is not found.
I checked all portable lib folders in packages and all of them are missing Nito.AsyncEx.Enlightenment.dll and also some of them are missing Nito.AsyncEx.Concurrent.dll.
Can this be fixed somehow?
P.S. Folders I checked:
portable-net40+netcore45+MonoTouch+MonoAndroid
portable-net40+netcore45+sl4+wp71+MonoTouch+MonoAndroid
portable-net40+netcore45+sl5+wp8+wpa81+MonoTouch+MonoAndroid
portable-net45+netcore45+wp8+wpa81+MonoTouch+MonoAndroid
portable-net45+netcore45+wpa81+MonoTouch+MonoAndroid
Many thanks, Anatoliy
TaskCompleted
is not assigned if the Task
has already completed but the documentation states that the Property is never null
.
Thanks so much to Stephen Cleary for this great library!
I would like to offer the following small contribution to AsyncLock
This is copy-right free. You are granted an unconditional perpetual worldwide license to use this software in any way you would like, at your own risk.
/// Usage:
/// using (var lockToken = theLock.TryLock()) {
/// if (lockToken == null) { do_pretty_much_nothing(); }
/// else { do_something_using_critical_resource(); }
/// }
private readonly IDisposable _releaserObject;
public AsyncLock()
{
_releaserTask = Task.FromResult((IDisposable)new Releaser(this));
_releaserObject = new Releaser(this);
}
public IDisposable TryLock() // sjb: added
{
if (_semaphore.Wait(0)) { // Doesn't wait. Timeout is 0 milliseconds.
return _releaserObject;
} else {
return null;
}
}
As you said here on 2014-05-07:
I have been giving it a lot of thought, and I have decided that the Bait-and-Switch approach described by Paul Betts is a better solution than the one described below."
Are you planning to refactor AsyncEx library according with the Bait-and-Switch approach?
When adding to an AsyncProducerConsumerQueue a .NET 4.5 application is sometimes getting a
"Deque is empty" exception. Tracing through this happens inside AsyncLock when releasing the lock protecting the AsyncProducerConsumerQueue. The exception is generated in the Deque class RemoveFromFront.method.
What is the recommended way to cancel a Task passed to NotifyTaskCompletion? I see that NotifyTaskCompletionImplementation
passes in CancellationToken.None
but if I have a cancellation token associated with my task should that be passed in?
Nito.AsyncEx.AsyncCollection<>
has low performance, according to benchmarks from another AsyncCollections project, and that project contains very fast producer/consumer AsyncCollection
, AsyncQueue
and AsyncStack
. I'm thinking that it would be a good idea to improve performance of Nito.AsyncEx.AsyncCollection<>
according with practices used in that lib.
I was switching a BlockingCollection with an AsyncCollection and discovered TryTake operation on AsyncCollection is blocking when the collection is empty, where I'd expect it to return false immediately. Is this behaviour by design?
Hi Stephen,
It seems the assemblies in the 3.0 NuGet package are missing a strong name.Thus they cannot be referenced from strong-named assemblies.
Cheers,
Markus
Is there any reason behind this? The sync version has an overload for one.
Does it need ?
_tcs.TrySetResultWithBackgroundContinuations();
It can be expensive to call it frequently
Was looking at the AsyncLazy<T>
implementation, and thinking why the class wasn't just implemented like this:
public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<Task<T>> valueFactory)
:base(valueFactory)
{
}
public Task<T> ValueAsync()
{
return this.Value;
}
}
A use-case:
public class Foo { }
public class FooService
{
private AsyncLazy<Foo> _lazyFoo;
public FooService()
{
_lazyFoo = new AsyncLazy<Foo>(LoadFooAsync);
}
// This method returns a cached result on subsequent calls.
public Task<Foo> GetFooAsync()
{
return _lazyFoo.ValueAsync();
}
private async Task<Foo> LoadFooAsync()
{
// In some cases (HttpWebRequest on WP8 for example) this should be started on UI thread.
Debug.WriteLine("LoadFooAsync Start: {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Delay(500);
Debug.WriteLine("LoadFooAsync Finish: {0}", Thread.CurrentThread.ManagedThreadId);
return new Foo();
}
}
The implementation of AsyncLazy<T>
in the library explicitly sends the factory method on the thread-pool via Task.Run(...)
, which, in my opinion, has a few implications:
ArgumentException
is overkill. In either case, it should be responsibility of the asynchronous method to not hold the thread so long.HttpWebRequest
in WP8 should be called from UI thread (otherwise it will likely deadlock the UI thread, because internally it implemented around the web browser control and tries to sync back to UI thread to send the request).Are there any serious drawbacks in the implementation of the AsyncLoad<T>
as above?
Thanks!
Need to update all dependent package versions (MS.Bcl, etc). Currently (v3.0.0, v3.0.1), installing into a .NET 4 package requires a manual update of dependent packages before a build can be done.
This prevents them from being used in strong named projects, which can be easily resolved by signing them.
Package current doesn't work on IOS unified projects :(
MTOUCHTASK: error MT2002: Failed to resolve assembly: 'Nito.AsyncEx.Enlightenment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null'
Any change for a quick fix?
What is the reasoning behind AsyncManualResetEvent WaitAsync method not supporting a CancellationToken? The documentation state "WaitAsync does not have explicit CancellationToken support because there are no state changes when a wait is satisfied."1 however if the AsyncManualResetEvent is never set this Task will not complete.
What is the guidance for accomplishing this behavior? The only solution I can come up with is to register a continuation on the cancellation token to set the AsyncManualResetEvent when cancelled. After the WaitAsync throw the cancellation exception.
I have the following code, which I want to timeout without throwing an exception via a cancelation token via waitAsync (This code runs a ton and we don't want a trillion exceptions thrown). The problem is, we don't know if it timed out or passed through via the resetEvent so we want to reset the resetEvent (https://github.com/exceptionless/Foundatio/blob/async/src/Core/Lock/CacheLockProvider.cs#L37-L74)
var resetEvent = new AsyncManualResetEvent(false);
var sw = Stopwatch.StartNew();
await Task.WhenAny(Task.Delay(100), resetEvent.WaitAsync()).ConfigureAwait(false);
sw.Stop();
Assert.InRange(sw.ElapsedMilliseconds, 100, 110);
sw.Restart();
resetEvent.Reset();
sw.Stop();
Assert.InRange(sw.ElapsedMilliseconds, 0, 5);
sw.Reset();
await Task.WhenAny(Task.Delay(100), resetEvent.WaitAsync()).ConfigureAwait(false);
sw.Stop();
Assert.InRange(sw.ElapsedMilliseconds, 100, 110);
The bug we see is that when we call resetEvent.Reset() the last Task.WhenAny() completes immediately. We think it should wait 100ms as it's been reset, but by looking at the code we see that the underlying tsc isn't reset.
The problem is described in this StackOverflow question: http://stackoverflow.com/questions/28703336/nuget-pcl-library-conflict
To fix this issue, you would need to depend on the Microsoft.Bcl.Async package for all platforms (even those that natively support async), and return the TaskAwaiter from the Microsoft.Runtime.CompilerServices in all cases.
When using AsyncLock.LockAsync() in combination with only synchronous running code a StackOverflowException can happen during dispose/unlock.
The following code snippet runs into the StackOverflow:
public static async Task NitoRunIntoStackOverflowAsync()
{
const int locksToTake = 5000;
AsyncLock nitoLock = new AsyncLock();
Task[] tasks = new Task[locksToTake];
using (await nitoLock.LockAsync())
{
for (int i = 0; i < locksToTake; i++)
{
tasks[i] = Task.Run(async () =>
{
using (await nitoLock.LockAsync())
{
//Any synchronous running code...
await Task.FromResult(true);
}
});
}
}//Disposing will trigger the stackoverflow
await Task.WhenAll(tasks);
}
Will result in the following stack (taken from windbg - read bottom up):
Nito.AsyncEx.AsyncLock+Key.System.IDisposable.Dispose()
//class.method awaiting the lock
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run()
System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action, Boolean, System.Threading.Tasks.Task ByRef)
System.Threading.Tasks.Task.FinishContinuations()
System.Threading.Tasks.Task`1[[System.__Canon, mscorlib]].TrySetResult(System.__Canon)
System.Threading.Tasks.TaskCompletionSource`1[[System.__Canon, mscorlib]].TrySetResult(System.__Canon)
Nito.AsyncEx.DefaultAsyncWaitQueue`1+CompleteDisposable[[System.__Canon, mscorlib]].Dispose()
Nito.AsyncEx.AsyncLock.ReleaseLock()
Nito.AsyncEx.AsyncLock+Key.System.IDisposable.Dispose()
Shouldn't the call to TaskCompletionSource<T>.TrySetResult
in the CompleteDisposable
be replaced with either an offload like TrySetResultWithBackgroundContinuations
despite the performance implications or one of the possibilities from this SO thread (as far as I remember you participated in there)
I think that would be awesome.
The "3.0.1" packet on NuGet seems to contain the "3.0.1-pre" binaries instead. Also all dll file dates match the 3.0.1-pre release date. I cannot build my app because it fails to resolve the dependency. Only when I remove 3.0.1 and install 3.0.0, I can build and run my app. Can you please check what is wrong with the 3.0.1 package?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.