TaskCompletionSource to represent Async - asynchronous

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

Related

Blazor InvokeAsync vs await InvokeAsync

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);
}

Dart Future.doWhile blocks all execution

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)

Best place to load data when navigating XamarinForms Prism 6?

One of the cool features in Prism 6 is the deep linking and passing parameters. In a lot of cases, you'd want to use this parameter to look up data from a web service. Ideally this would be using async/await to get the data. Where is the best place to do this? The OnNavigatedTo method for example is a void.
Although I don't have a case for Deep Linking yet, I am doing many loads on many pages inside OnNavigatedTo and it is working great!
Here is a sample:
public void OnNavigatedTo(NavigationParameters parameters)
{
if (parameters != null &&
parameters.ContainsKey("MyKey"))
{
SomePrivateFieldInViewModel = (YourVariable)parameters["MyKey"];
//SomeWork
}
GetItems();
}
private async void GetItems()
{
try
{
SomeListInViewModel = await WebServices.GetEntity(SomePrivateFieldInViewModel);
//SomeWork
}
catch (Exception ex)
{
//SomeWork
}
}

ASP.NET HttpContext.Current inside Task.Run

I have a following code example that is used in ASP.NET MVC application.
The purpose of this code is to create "fire and forget" request for queuing some long running operation.
public JsonResult SomeAction() {
HttpContext ctx = HttpContext.Current;
Task.Run(() => {
HttpContext.Current = ctx;
//Other long running code here.
});
return Json("{ 'status': 'Work Queued' }");
}
I know this is not a good way for handling HttpContext.Current in asynchronous code, but currently our implementation not allows us to do something else.
I would like to understand how much this code is dangerous...
The question: Is it theoretically possible that setting the HttpContext inside Task.Run, will set the context to totally another request?
I think yes, but I'm not sure. How I understand it:
Request1 is handled with Thread1 from thread pool, then while Thread1 is handling absolutelly another request (Request2), the code inside Task.Run will set context from Request1 to Request2.
Maybe I am wrong, but my knowledge of ASP.NET internals not allows me to understand it correctly.
Thanks!
Let me bump a little internals on you:
public static HttpContext Current
{
get { return ContextBase.Current as HttpContext; }
set { ContextBase.Current = value; }
}
internal class ContextBase
{
internal static object Current
{
get { return CallContext.HostContext; }
set { CallContext.HostContext = value; }
}
}
public static object HostContext
{
get
{
var executionContextReader = Thread.CurrentThread.GetExecutionContextReader();
object hostContext = executionContextReader.IllogicalCallContext.HostContext;
if (hostContext == null)
{
hostContext = executionContextReader.LogicalCallContext.HostContext;
}
return hostContext;
}
set
{
var mutableExecutionContext = Thread.CurrentThread.GetMutableExecutionContext();
if (value is ILogicalThreadAffinative)
{
mutableExecutionContext.IllogicalCallContext.HostContext = null;
mutableExecutionContext.LogicalCallContext.HostContext = value;
return;
}
mutableExecutionContext.IllogicalCallContext.HostContext = value;
mutableExecutionContext.LogicalCallContext.HostContext = null;
}
}
So
var context = HttpContext.Current;
is equal to (pseudocode)
var context = CurrentThread.HttpContext;
and inside your Task.Run something like this happens
CurrentThread.HttpContext= context;
Task.Run will start new task with thread from thread pool. So you're telling that your new thread "HttpContext property" is reference to starter thread "HttpContext property" - so far so good (well with all the NullReference/Dispose exceptions you'll be facing after your starter thread finishes). Problem is if inside your
//Other long running code here.
You have statement like
var foo = await Bar();
Once you hit await, your current thread is returned to thread pool, and after IO finishes you grab new thread from thread pool - wonder what its "HttpContext property" is, right ? I don't know :) Most probably you'll end with NullReferenceException.
The issue you will run into here is that the HttpContext will dispose when the request is complete. Since you aren't awaiting the result of the Task.Run, you are essentially creating a race condition between the disposal of the HttpContext and it's usage within the task.
I'm pretty sure that the only issue your task will run into is a NullReferenceException or an ObjectDisposedException. I don't see any way where you could accidentally steal another request's context.
Also, unless you are handling & logging exceptions within your task, your fire and forget will throw and you'll never know about it.
Check out HangFire or consider using a message queue for processing backend jobs from a separate process.

How do i improve the legacy code implementation, Response.Redirect?

Some scenarios to ponder. There is a legacy code which has following implementation Example1 and Example2. If we try to implement MSDN recommendation then the legacy code fails.
Here is a Legacy code example:
Example 1:
void Page_Load() {
.... some code
if(condition) {
/// some condition
} else {
RedirectPage(url);
}
// another code block
// some other conditions.
}
Example 2:
a. File1.ascx
void Page_Load() {
try {
.. some code
base.CheckPreference();
RedirectPage(defaultPage);
}
catch(Exception ex) {
ExceptionHandling.GetErrorMessage(ex);
}
}
b. BaseClass.cs // this is the base class
void CheckPreference() {
try {
if(condition) {
RedirectPage(url1);
} else if(condition2) {
RedirectPage(url2);
} else {
// update session
}
}
catch(Exception ex) {
ExceptionHandling.GetErrorMessage(ex);
throw;
}
}
void RedirectPage(string url) {
Response.Redirect(url);
}
One possible way is to add a boolean field in the class e.g endExecution, set the field to true whenever RedirectPage is called.
We have to update RedirectPage code see code snippet below:
// Updated code - MSDN recommendation.
void RedirectPage(url) {
Response.Redirect(url, false);
this.Context.ApplicationInstance.CompleteRequest();
endExecution = true;
}
Please suggest some other better ways to improve the legacy code implementation.
Probably the most unintuitive thing for folks issuing a redirect is that in our minds we've already returned from the method what we call Respond.Redirect (or whatever the equivilent is in your language/platform of the day. All we've done is call a method.
Bottom line is that you have to stop processing the request to avoid trying to commit to responses for the same request. That would throw an exception on just about any platform I've worked with.
ASP.NET MVC improved this with the ActionResponse so that you are returning from the method (and terminating the remainder of request processing) with code that looks like this:
return Redirect(url);
Bottom line is that you need to get in the habit of returning from your event right after you perform your redirect. Any deviation from that habit needs to be documented in the code why. This will help make the application perform the way you expect.
The approach that you've taken is perfectly reasonable.

Resources