I’m struggling a bit to understand why the following code doesn’t work (note: this is a contrived example, I am trying to understand how to use doWhile).
bool busy = true;
void doSomething() async {
await Future.doWhile(() => busy);
print("done");
}
void doSomethingElse() async {
await Future.delayed(
Duration(seconds: 2), (){
busy = false;
});
}
void main() {
print("a");
doSomething();
doSomethingElse();
print("b");
}
I would have thought that this would print:
a
b
done
But it instead just blocks permanently (or at least on dartpad it does). Could someone please help me understand what is wrong here?
My best guess is that the doWhile is repeatedly scheduling itself as soon as it is called so that no other code can ever be executed. If that is the case, how can one use doWhile normally?
(I am aware of Completer and similar, I’m just specifically interested in doWhile here)
Related
Edit: for clarification, this is in a Blazor Server application
I'm confused about the correct usage of InvokeAsync and updating the UI. The documentation has several usages without really explaining the reason for awaiting or not awaiting. I have also seen some contradictory threads without much to backup their reasoning.
It seems wrong to make all methods async to await InvokeAsync(StateHasChanged) and I read somewhere that the reason InvokeAsync was introduced was to prevent the need for async code everywhere. But then what situations might I want to await it?
awaiting:
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-5.0&viewFallbackFrom=aspnetcore-3.0#invoke-component-methods-externally-to-update-state
non-await discard:
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/rendering?view=aspnetcore-5.0
Here are some examples of different usages that I have seen, if anyone could explain or share any links with information on some of the differences between them that'd be great (thanks!)
public void IncrementCounter()
{
_counter++;
InvokeAsync(StateHasChanged);
}
public void IncrementCounter()
{
InvokeAsync(() =>
{
_counter++;
StateHasChanged);
}
}
public async Task IncrementCounter()
{
_counter++;
await InvokeAsync(StateHasChanged);
}
public async Task IncrementCounter()
{
await InvokeAsync(() =>
{
_counter++;
StateHasChanged();
});
}
IncrementCounter (a ButtonClick handler) is the wrong thing to look at - it always runs on the SyncContext thread and can always use a plain StateHasChanged() without Invoke.
So lets look at a Timer event instead. The Threading.Timer class does not support async handlers so you run in a void Tick() { ... } on an unspecified thread.
You do need InvokeAsync(StateHasChanged) here. You could make the Tick method an async void just to await the InvokeAsync but that gives of the wrong signals. Using InvokeAsync without await is the lesser evil.
void Tick() // possibly threaded event handler
{
_counter++;
InvokeAsync(StateHasChanged); // fire-and-forget mode
}
But when you are in an async method and still need InvokeAsync, it is neater to await it, just because you can.
async Task SomeService()
{
_counter++;
await InvokeAsync(StateHasChanged);
}
Below the code snippet I was talking about:
void getlocation() async {
Position position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.low);
print(position);
}
I need to write this function in terms of Future in Dart (Flutter).
Thanks in advance.
Version of future, then method.
Future - It is used to represent a potential value, or error, that will be available at some time in the future.
Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.best)
.then((Position position) {
print('Latitude : ${position.latitude}');
print('Longitude : ${position.longitude}');
}).catchError((err) {
print(err);
});
Note : If you want your program to wait until the async function completes, then use await or else use then.
I have the following WebAPI action and is wondering if returning Task<bool> and return _store.ContainerExistsAsync(container) directly is better;
I ask because, if I understand async/await correctly, the compiler creates a statemachine at the await to return to the same state. Returning the task directly without having to await it in the action, would that be theoretical faster?
public async Task<HttpResponseMessage> GetContainer(string container)
{
if (container.Length < 3 ||
container.Length > 63 ||
!Regex.IsMatch(container, #"^[a-z0-9]+(-[a-z0-9]+)*$"))
return Request.CreateResponse(HttpStatusCode.BadRequest, new { errors = new string[1] { "Container Name is not alowed." } })
return Request.CreateResponse<bool>(HttpStatusCode.OK, await _store.ContainerExistsAsync(container));
}
Yes, if you can implement an asynchronous method without async and await, then go ahead; async/await will add overhead.
This is commonly seen when the last line of a method has the only await and looks like return await ...;
In your particular example, I'm not 100% sure whether this would work since the method is doing something after the await.
It's easy enough to make it return the Task<bool> from ContainerExistsAsync directly, but the error handling would also need to change. If throwing a HttpResponseException works well enough, then yes, you would be able to implement an asynchronous method without using async.
Consider the following (based on the default MVC template), which is a simplified version of some "stuff" that happens in the background - it completes fine, and shows the expected result, 20:
public ActionResult Index()
{
var task = SlowDouble(10);
string result;
if (task.Wait(2000))
{
result = task.Result.ToString();
}
else
{
result = "timeout";
}
ViewBag.Message = result;
return View();
}
internal static Task<long> SlowDouble(long val)
{
TaskCompletionSource<long> result = new TaskCompletionSource<long>();
ThreadPool.QueueUserWorkItem(delegate
{
Thread.Sleep(50);
result.SetResult(val * 2);
});
return result.Task;
}
However, now if we add some async into the mix:
public static async Task<long> IndirectSlowDouble(long val)
{
long result = await SlowDouble(val);
return result;
}
and change the first line in the route to:
var task = IndirectSlowDouble(10);
then it does not work; it times out instead. If we add breakpoints, the return result; in the async method only happens after the route has already completed - basically, it looks like the system is unwilling to use any thread to resume the async operation until after the request has finished. Worse: if we had used .Wait() (or accessed .Result), then it will totally deadlock.
So: what is with that? The obvious workaround is "don't involve async", but that is not easy when consuming libraries etc. Ultimately, there is no functional difference between SlowDouble and IndirectSlowDouble (although there is obvious a structural difference).
Note: the exact same thing in a console / winform / etc will work fine.
It's to do with the way the synchronization context is implemented in ASP.NET (Pre .NET 4.5). There's tons of questions about this behavior:
Task.WaitAll hanging with multiple awaitable tasks in ASP.NET
Asp.net SynchronizationContext locks HttpApplication for async continuations?
In ASP.NET 4.5, there's a new implementation of the sync context that's described in this article.
http://blogs.msdn.com/b/webdev/archive/2012/11/19/all-about-httpruntime-targetframework.aspx
When you use .Result there is always a possibility of deadlock because .Result is blocking by nature. The way to avoid deadlocks is to not block on Tasks (you should use async and await all the way down). The subject is in details described here:
Don't Block on Async Code
One fix is to add ConfigureAwait:
public static async Task<long> IndirectSlowDouble(long val)
{
long result = await SlowDouble(val).ConfigureAwait(false);
return result;
}
Another fix is to use async/await throughout:
public async Task<ActionResult> Index()
{
var task = IndirectSlowDouble(10);
long result = await task;
ViewBag.Message = result.ToString();
return View();
}
Sorry my knowledge with threads is still a bit weak.
Just reading around. If you use TaskCompletionSource to represent some IO Async operation.
Like say some DownloadAsync, you are not tying up a thread as I understand?
I always thought when something is happening asynchronously it must be tying up a thread?
Any clarification is appreciated.
Thanks
The DownloadFileAsync of the webclient provides a good opportunity to apply TPL in a Event based asynchronous model.
Since the action that includes the call to the DownloadFileAsync completes quickly, the real work isn't done until the DownloadFileCompleted event is triggered. This is where the TaskCompletionSource comes into play.
var downloadCompletionSource = new TaskCompletionSource<bool>();
webClient.DownloadFileCompleted+=
(s, e) =>
{
if (e.Error != null)
{
downloadCompletionSource.SetException(e.Error);
}
else
{
downloadCompletionSource.SetResult(true);
}
}
};
webClient.DownloadFileAsync(new Uri(downloadUrl), destinationFilePath);
try
{
downloadCompletionSource.Task.Wait();
}
catch (AggregateException e)
{
}
More can be found here in MSDN