I am have the following code to load XDocument from Stream in .NET Core 2
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
XDocument xdocument = await XDocument.LoadAsync(xmlStream, new LoadOptions(), token);
CancellationToken is required parameter. but i what's the use of CancellationToken here?
How cancellation token can be used in this case
When you are inside an async method, you should have received a cancellation token as a parameter. If you did, you can check the cancellation state (if cancellation has been requested by the caller) and act accordingly (throw an exception or break the operation) and pass on this token to the async methods you call.
If you did not receive a token, you may construct it yourself (as you did) and pass that on. In that case you are in control of the token source and can cancel the whole operation yourself.
If you do not want to make use of the cancel feature, you do not have to call Cancel - it depends on the nature of the method you are writing. You may want to cancel a long-running async method based on user input or a timer. This is just an option offered by cancelable async methods (like LoadAsync in your question).
https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation
In the latter case make sure you dispose the token source - preferably using a using block.
Related
My Lambda function is required to send a token back to the step function for it to continue, as it is a task within the state machine.
Looking at my try/catch block of the lambda function, I am contemplating:
The order of SendTaskHeartbeatCommand and SendTaskSuccessCommand
The required parameters of SendTaskHeartbeatCommand
Whether I should add the SendTaskHeartbeatCommand to the catch block, and then if yes, which order they should go in.
Current code:
try {
const magentoCallResponse = await axios(requestObject);
await stepFunctionClient.send(new SendTaskHeartbeatCommand(taskToken));
await stepFunctionClient.send(new SendTaskSuccessCommand({output: JSON.stringify(magentoCallResponse.data), taskToken}));
return magentoCallResponse.data;
} catch (err: any) {
console.log("ERROR", err);
await stepFunctionClient.send(new SendTaskFailureCommand({error: JSON.stringify("Error Sending Data into Magento"), taskToken}));
return false;
}
I have read the documentation for AWS SDK V3 for SendTaskHeartbeatCommand and am confused with the required input.
The SendTaskHeartbeat and SendTaskSuccess API actions serve different purposes.
When your task completes, you call SendTaskSucces to report this back to Step Functions and to provide the results from the Task that your workflow can then process. You do not need to call SendTaskHeartbeat before SendTaskSuccess and the usage you have in the code above seems unnecessary.
SendTaskHeartbeat is optional and you use it when you've set "HeartbeatSeconds" on your Task. When you do this, you then need your worker (i.e. the Lambda function in this case) to send back regular heartbeats while it is processing work. I'd expect that to be running asynchronously while your code above was running the first line in the try block. The reason for having heartbeats is that you can set a longer TimeoutSeconds (or dynamically using TimeoutSecondsPath) than HeartbeatSeconds, therefore failing / retrying fast when the worker dies (Heartbeat timeout) while you still allow your tasks to take longer to complete.
That said, it's not clear why you are using .waitForTaskToken with Lambda. Usually, you can just use the default Request Response integration pattern with Lambda. This uses the synchronous invoke mode for Lambda and will return the response back to you without you needing to integrate back with Step Functions in your Lambda code. Possibly you are reading these off of an SQS queue for concurrency control or something. But if not, just use Request Response.
Imagine you've built a React form using React Hooks and the Context API. When the user presses Submit you need to run validation, which consists of checking whether various e-mail addresses already exist, various company names already exist, and perhaps some other async checks need to be made too.
Each of these will be executed independently and you have no guarantee that any specific one of them will be the last to finish.
When you start the validation, you set an isProcessing flag to true. When all of the aforementioned checks are complete, you will set isProcessing to false.
Given that one async call knows nothing about the other async calls, what's a good pattern to manage this situation? Simply put, how do you know when ALL of the async calls are done so that isProcessing can be set to false and a POST request can be made?
You're on the right track,
But generally if all of it are async you should probably use
Promise.all()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
Then you can use a single await for all of your async process.
Turn on the isProcessing then false it after the Promise.all finishes running all of your async validations.
But efficiently wise, I think its better to setup your validation in one single async functions, handling them differently is inefficient and has many calls, though there are special cases in which you depend in third party apis.
Your code should probably something along these
useEffect(()=>{
async function validateFields(){
// setState isProcessing true
const asyncValidation1 = promiseFunction();
const asyncValidation2 = promiseFunction();
const result = await Promise.all(asyncValidation1 , asyncValidation2);
// Handle the result
// setState isProcessing false
}
validateFields();
},[])
Notice that I wrapped the validation function into a async function. This is because declaring async useEffect is bad practice.
My OnAppearing code looks like this. I don't understand what this is added for:
`await Task.Yield()`
Can someone explain what this does?
protected override async void OnAppearing()
{
base.OnAppearing();
Utils.SetState(Settings.mode.Text(), vm.Mode);
vm.CfsLabel = Settings.cfs.Text();
SetMode(Settings.mode.Text());
Subscribe();
ContentPageStack.IsVisible = true;
if (!openedOnce)
{
// can someone explain what the following line
// is doing here in the code. What's the Task
// that it refers to and what does Yield do?
await Task.Yield();
await scroll.ScrollToAsync(0, 0, false);
openedOnce = true;
}
if (App.devIsUser)
Analytics.TrackEvent(VersionTracking.CurrentVersion + " - On Appearing - home page");
}
In this particular case, await Task.Yield does nothing useful. It is probably a misguided attempt to process Win32 messages like WM_PAINT. I.e., a "poor man's DoEvents".
await Task.Yield is used to force asynchrony. It's a way of forcing await to behave asynchronously, returning to the caller. It also immediately queues the remainder of the method to run.
The reason this doesn't work as a "poor man's DoEvents" is because the Win32 message queue is prioritized. So this is what the await Task.Yield actually does in this particular instance:
Queues the continuation of the async method to the current context (the UI SynchronizationContext), which places the continuation into the Win32 message queue.
Returns from the async method. Since this is an event handler, this returns to the Win32 message processing loop.
The Win32 message process loop pulls the next message from its queue. Since the queue is prioritized, it will always skip over regular Win32 messages and take the continuation message.
The loop processes the message, which runs the continuation of the async method, so the event handler resumes executing right where it left off.
I think the Microsoft docs give you a clear picture of what it does, When you read about Task.Yield its says:
Creates an awaitable task that asynchronously yields back to the current context when awaited.
Returns
YieldAwaitable
A context that, when awaited, will asynchronously transition back into the current context at the time of the await. If the current SynchronizationContext is non-null, it is treated as the current context. Otherwise, the task scheduler that is associated with the currently executing task is treated as the current context.
What this basically means is when you use await Task.Yield in an async method it will force the method to complete asynchronously. And if there is a Synchronization Context available it will execute the remainder of the method's execution back to that context.
Note: The synchronization context that is present on a UI thread in most UI environments will often prioritize work posted to the context higher than input and rendering work. For this reason, do not rely on await Task.Yield(); to keep a UI responsive.
what is the proper implementation of SendAsync method of Azure ServiceBus TopicClient?
In the second implementation, will the BrokeredMessage actually be disposed before the SendAsync happens?
public async Task SendAsync<TMessage>(TMessage message, IDictionary<string, object> properties = null)
{
using (var bm = MessagingHelper.CreateBrokeredMessage(message, properties))
{
await this._topicClient.Value.SendAsync(bm);
}
}
public Task SendAsync<TMessage>(TMessage message, IDictionary<string, object> properties = null)
{
using (var bm = MessagingHelper.CreateBrokeredMessage(message, properties))
{
return this._topicClient.Value.SendAsync(bm);
}
}
I would like to get most from await/async pattern.
Answer to your question: the second approach could cause issues with disposed objects, you have to wait ending of SendAsync execution before you can release resources.
Detailed explanation.
If you call await, execution of a method will be stopped at the same moment and will not continue till awaitable method is not returned. Brokered message will be stored in a local hidden variable and will not be disposed.
If you don't call await, execution will continue and all resources of brokered message will be freed before they are actually consumed (as using is calling Dispose on object at the end) or in the process of consumption. This definetely will lead to exceptions inside SendAsync. At this point, execution of SendAsync is actually started.
What await does is “pausing” any current thread and waits for completion of task and it's result. And that's what you actually need. Purpose of async-await is to allow execution of some task concurrently with something else, it provides ability to wait for a result of concurrent operation when it is really necessary and further execution isn't possible without it.
First approach is good if every method to the top is an async method too. I mean, if caller of your SendAsync is async Task, and caller of that caller and so on to the top calling method.
Also, consider exceptions that could raise, they are listed here. As you can see, there are so-called transient errors. This is a kind of errors that retry can possibly fix. In your code, there is no such exception handling. Example of retry pattern could be found here, but mentioned article on exceptions can suggest better solutions and it is a topic of another question. I would also add some logging system to at least be aware of any non transient exceptions.
I have a Web API project whose controller in turn makes web requests to a third party REST interface. My controller CRUD functions i have marked as async however the implementation is such that i use HttpWebRequest blocking functions GetRequestStream and GetResponse.
Is this suitable or should i use the Begin/End methods of HttpWebRequest too. This seems like overkill as it would be asyncing an already async operation, or would it allow more concurrent outgoing web requests?
Looking for the best solution for throughput both incoming and outgoing.
the controller is marked async but the implementation uses synchronous HttpWebRequest calls, in that my controller is awaiting Task.Run( sync web request )
Think about what is happening in the request. The request comes in and ASP.NET takes a thread pool thread to handle the request. The controller action queues the work to the thread pool (taking up another thread), and then awaits that work, freeing up the original request thread. You haven't gained anything by using await because there's still a thread pool thread blocking on the web request.
For this reason, you should almost never use Task.Run (or any other method that queues work to the thread pool) on ASP.NET.
Is this suitable or should i use the Begin/End methods of HttpWebRequest too. This seems like overkill as it would be asyncing an already async operation
It's not really asynchronous right now; there's still a thread being blocked. I call this "queue blocking work to a thread pool thread and then await it" technique fake asynchrony.
The appropriate fix is to use HttpClient, which was designed for asynchronous use; or, you could use TaskFactory<T>.FromAsync to wrap the Begin/End methods into an awaitable task.
The thing i dont understand though is if i use await HttpClient.SendAsync then somewhere something must be blocking waiting for a response
No, there doesn't have to be something blocking somewhere. As I describe on my blog, in a truly asynchronous scenario (i.e., not fake-asynchrony), there is no thread.
I would recommend you to retain the async methods, and use HttpClient instead of HttpWebRequest, because it supports asynchronous calls as well.
Let's have a look at a pseudo example of a CarsController calling a third party service.
public class CarsController : ApiController
{
[Route("cars/{id}")]
public async Task<IHttpActionResult> Get(int id)
{
//Get a car by its id
HttpClient client = new HttpClient();
//Read the content directly
string result = await client.GetStringAsync("http://www.google.com");
//process the result returns from the thrid party REST service
return Ok(result);
}
}
As you can see, HttpClient supports reading String/ Stream/ ByteArray asynchronously via GetXXXAsync() methods.
If you want to access to the underlying response content, that can be achieved by using the following code:
[Route("responsecars/{id}")]
public async Task<IHttpActionResult> GetResponseStream(int id)
{
HttpClient client = new HttpClient();
HttpResponseMessage responseMessage =await client.GetAsync("http://www.google.com", HttpCompletionOption.ResponseContentRead);
HttpContent content = responseMessage.Content;
//using one of the ReadAsync methods
string text =await content.ReadAsStringAsync();
return Ok(text);
}
Hope this help.
Asynchrony on the server is separate and independent from asynchrony on the client.
You can call a synchronous Web API method asynchronously from the client with WebRequest.GetResponseAsync, or you can call an asynchronous Web API method synchronously from the client with WebRequest.GetResponse, or you can have asynchrony on both sides, which is probably the best approach. You don't need to use Begin/End APM-style WebRequest APIs, unless you target .NET 4.0 on the client. Use Task-based async APIs instead.
In either case, a complete HTTP request will be sent to the client when your Web API controller method has fully finished, regardless of whether it is implemented as synchronous or asynchronous (Task-based).