I have this code to check if Server is available or not:
public static async Task<bool> PingServer()
{
System.Net.NetworkInformation.Ping p1 = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingReply PR = await p1.SendPingAsync("pc2");
// check when the ping is not success
if (PR.Status != System.Net.NetworkInformation.IPStatus.Success)
{
return false;
}
return true;
}
Now, my problem is that SendPingAsync does not support CancellationTokenSource so how can I cancel the last ping to perform a new one to prevent a lot of pings?
When the server is lost it takes seconds to PingServer() return a false value.
This is how I call PingServer():
var task = await PingServer();
if (task == true)
{
//do some stuff like retrieve a table data from SQL server.
}
Why I use ping? because when I want to get a table from SQL server if the server is disconnected my app enter a breakpoint.
public async static Task<System.Data.Linq.Table<Equipment>> GetEquipmentTable()
{
try
{
DataClassesDataContext dc = new DataClassesDataContext();
// note : i tried so many ways to get table synchronize but it still freeze my UI !
return await Task.Run(() => dc.GetTable<Equipment>());
}
catch
{
return null;
}
}
EDIT : I used ping to reduce chance of entering my app in brake mode by getting a table from database. is there any other way to prevent break mode ? is it best way to ping server before calling dc.GetTable() ?
Have you considered using the timeout parameter?
From the documentation:
This overload allows you to specify a time-out value for the
operation.
If that doesn't suffice and your problem is that the ping call is blocking, you could perform it on a background thread providing this is tightly controlled.
Consider
public static async Task<bool> PingServer() {
using (var ping = new System.Net.NetworkInformation.Ping()) {
try {
var maxDelay = TimeSpan.FromSeconds(2); //Adjust as needed
var tokenSource = new CancellationTokenSource(maxDelay);
System.Net.NetworkInformation.PingReply PR = await Task.Run(() =>
ping.SendPingAsync("pc2"), tokenSource.Token);
// check when the ping is not success
if (PR.Status != System.Net.NetworkInformation.IPStatus.Success) {
return false;
}
return true;
} catch {
return false;
}
}
}
Where the ping is done with a cancellation token using Task.Run; If the ping result returns before the allotted time then all is well.
wrapped the component in a using to dispose of it when exiting function.
The system you depend on might fail, or the connection can go down right after your ping, when you're executing your code.
This is why a retry strategy is a much more robust approach then simply pinging a system before calling it.
Here is how you can implement a retry Cleanest way to write retry logic?
I would go with a retry approach, but if you still want to stay with your design you could
Schedule a periodic task to ping the system in question Is there a Task based replacement for System.Threading.Timer?
Make sure you schedule this periodic task in one central place (application startup or the like)
Invoke your PingServer from this periodic task and make sure you call Ping.SendAsync with PingOptions.Timeout being set, see this overload
From your PingServer set some kind of shared state, it could be a static variable, or an implementation of the Registry pattern
Make sure your shared state is thread-safe
The rest of your code can call this shared state, to find out if a system is online and available
As you can see, this approach is more complex, but you will prevent "lots of pings" to the system you depend on
Related
I've been working on a project and saw the below code. I am new to the async/await world. As far as I know, only a single task is performing in the method then why it is decorated with async/await. What benefits I am getting by using async/await and what is the drawback if I remove async/await i.e make it synchronous I am a little bit confused so any help will be appreciated.
[Route("UpdatePersonalInformation")]
public async Task<DataTransferObject<bool>> UpdatePersonalInformation([FromBody] UserPersonalInformationRequestModel model)
{
DataTransferObject<bool> transfer = new DataTransferObject<bool>();
try
{
model.UserId = UserIdentity;
transfer = await _userService.UpdateUserPersonalInformation(model);
}
catch (Exception ex)
{
transfer.TransactionStatusCode = 500;
transfer.ErrorMessage = ex.Message;
}
return transfer;
}
Service code
public async Task<DataTransferObject<bool>> UpdateUserPersonalInformation(UserPersonalInformationRequestModel model)
{
DataTransferObject<bool> transfer = new DataTransferObject<bool>();
await Task.Run(() =>
{
try
{
var data = _userProfileRepository.FindBy(x => x.AspNetUserId == model.UserId)?.FirstOrDefault();
if (data != null)
{
var userProfile = mapper.Map<UserProfile>(model);
userProfile.UpdatedBy = model.UserId;
userProfile.UpdateOn = DateTime.UtcNow;
userProfile.CreatedBy = data.CreatedBy;
userProfile.CreatedOn = data.CreatedOn;
userProfile.Id = data.Id;
userProfile.TypeId = data.TypeId;
userProfile.AspNetUserId = data.AspNetUserId;
userProfile.ProfileStatus = data.ProfileStatus;
userProfile.MemberSince = DateTime.UtcNow;
if(userProfile.DOB==DateTime.MinValue)
{
userProfile.DOB = null;
}
_userProfileRepository.Update(userProfile);
transfer.Value = true;
}
else
{
transfer.Value = false;
transfer.Message = "Invalid User";
}
}
catch (Exception ex)
{
transfer.ErrorMessage = ex.Message;
}
});
return transfer;
}
What benefits I am getting by using async/await
Normally, on ASP.NET, the benefit of async is that your server is more scalable - i.e., can handle more requests than it otherwise could. The "Synchronous vs. Asynchronous Request Handling" section of this article goes into more detail, but the short explanation is that async/await frees up a thread so that it can handle other requests while the asynchronous work is being done.
However, in this specific case, that's not actually what's going on. Using async/await in ASP.NET is good and proper, but using Task.Run on ASP.NET is not. Because what happens with Task.Run is that another thread is used to run the delegate within UpdateUserPersonalInformation. So this isn't asynchronous; it's just synchronous code running on a background thread. UpdateUserPersonalInformation will take another thread pool thread to run its synchronous repository call and then yield the request thread by using await. So it's just doing a thread switch for no benefit at all.
A proper implementation would make the repository asynchronous first, and then UpdateUserPersonalInformation can be implemented without Task.Run at all:
public async Task<DataTransferObject<bool>> UpdateUserPersonalInformation(UserPersonalInformationRequestModel model)
{
DataTransferObject<bool> transfer = new DataTransferObject<bool>();
try
{
var data = _userProfileRepository.FindBy(x => x.AspNetUserId == model.UserId)?.FirstOrDefault();
if (data != null)
{
...
await _userProfileRepository.UpdateAsync(userProfile);
transfer.Value = true;
}
else
{
transfer.Value = false;
transfer.Message = "Invalid User";
}
}
catch (Exception ex)
{
transfer.ErrorMessage = ex.Message;
}
return transfer;
}
The await keyword only indicates that the execution of the current function is halted until the Task which is being awaited is completed. This means if you remove the async, the method will continue execution and therefore immediately return the transfer object, even if the UpdateUserPersonalInformation Task is not finished.
Take a look at this example:
private void showInfo()
{
Task.Delay(1000);
MessageBox.Show("Info");
}
private async void showInfoAsync()
{
await Task.Delay(1000);
MessageBox.Show("Info");
}
In the first method, the MessageBox is immediately displayed, since the newly created Task (which only waits a specified amount of time) is not awaited. However, the second method specifies the await keyword, therefore the MessageBox is displayed only after the Task is finished (in the example, after 1000ms elapsed).
But, in both cases the delay Task is ran asynchronously in the background, so the main thread (for example the UI) will not freeze.
The usage of async-await mechanism mainly used
when you have some long calculation process which takes some time and you want it to be on the background
in UI when you don't want to make the main thread stuck which will be reflected on UI performance.
you can read more here:
https://learn.microsoft.com/en-us/dotnet/csharp/async
Time Outs
The main usages of async and await operates preventing TimeOuts by waiting for long operations to complete. However, there is another less known, but very powerful one.
If you don't await long operation, you will get a result back, such as a null, even though the actual request as not completed yet.
Cancellation Tokens
Async requests have a default parameter you can add:
public async Task<DataTransferObject<bool>> UpdatePersonalInformation(
[FromBody] UserPersonalInformationRequestModel model,
CancellationToken cancellationToken){..}
A CancellationToken allows the request to stop when the user changes pages or interrupts the connection. A good example of this is a user has a search box, and every time a letter is typed you filter and search results from your API. Now imagine the user types a very long string with say 15 characters. That means that 15 requests are sent and 15 requests need to be completed. Even if the front end is not awaiting the first 14 results, the API is still doing all the 15 requests.
A cancellation token simply tells the API to drop the unused threads.
I would like to chime in on this because most answers although good, do not point to a definite time when to use and when not.
From my experience, if you are developing anything with a front-end, add async/await to your methods when expecting output from other threads to be input to your UI. This is the best strategy for handling multithread output and Microsoft should be commended to come out with this when they did. Without async/await you would have to add more code to handle thread output to UI (e.g Event, Event Handler, Delegate, Event Subscription, Marshaller).
Don't need it anywhere else except if using strategically for slow peripherals.
My application uses MongoDB and I need to connect to the server and fetch some critical data when the application launches. If the connection attempt fails, I need to ask the user if he wants to try again or shutdown the application.
So far I went with the following solution:
public async Task LoadCriticalData()
{
bool IsBusy = true;
CancellationTokenSource Source = new CancellationTokenSource();
CancellationToken Token = Source.Token;
while (!Token.IsCancellationRequested)
{
try
{
await FetchCriticalData();
IsBusy = false;
Source.Cancel();
}
catch (Exception E)
{
bool Retry = RequestUserInteraction();
if (!Retry)
{
Source.Cancel();
CloseApplication();
}
}
}
}
I really don't like infinite loops (never used them for years before) but looks like there is no other way to implement this.
Is this sufficient or this can be done in a better way?
It is generally fine to retry an operation in a loop as long as there is some exit criteria. Either when the operation succeeds, or the operator selects to terminate the operation or application. In either case it is not truly an infinite loop.
Is Looping inside a task really recommended?
example code:
public void doTask(){
Task.Factory.StartNew(() => {
do{
// do tasks here.... call webservice
}while(true till cancelled)
});
}
any answers would be great! :)
because it is a case for my webservice calling right now, and the memory consumption goes out of control.
So may I ask, is looping inside a task really good or not recommended at all?
As Requested by SLC, heres the code:
CancellationTokenSource tokenSrc;
Task myTask;
private void btnStart_Click(object sender, EventArgs e)
{
isPressed = !isPressed;
if(isPressed)
{
tokenSrc = new CancellationTokenSource();
myTask = Task.Factory.StartNew(() =>
{
do{
checkMatches(tokenSrc.Token);
}while(tokenSrc.IsCancellationRequested != true);
}, tokenSrc.Token);
}
else {
try{
tokenSrc.Cancel();
// Log to notepad
}
catch(Exception err){
// Log to notepad
}
finally {
if(myTask.IsCanceled || myTask.IsCompleted || myTask.isFaulted) {
myTask.Dispose();
}
}
}
}
private void checkMatches(CancellationTokenSource token)
{
try
{
if(!token.IsCancellationRequested)
{
//Create Endpoint...
//Bypass ServCertValidation for test purposes
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate {return true;});
using(WebServiceAsmx.SoapClient client = new....)
{
client.CheckResp response = client.chkMatch();
// if's here for the response then put to logs
}
}
}
catch(Exception err)
{
// err.toLogs
}
}
It's perfectly fine to do this, especially if your task runs constantly, for example picking up a message queue.
while (not shutting down)
get next email to send
if exists next email to send
send
else
wait for 10 seconds
wend
Ensure that you have a way to get out if you need to cancel it, like you've done with a flag, and you should be fine.
Regarding webservices:
You should have no problem calling the webservice repeatedly, nor should it cause any memory spikes. However, you should make sure your initialisation code is not inside the loop:
BAD
while (notShuttingDown)
make a new connection
initialise
make a call to the service()
wend
GOOD
make a new connection
initialise
while (notShuttingDown)
make a call to the service
wend
Depending on your webservice it might be more optimal to create a batch operation, for example if your service is HTTP then hitting it repeatedly involves a lot of overhead. A persistent TCP connection might be better because it could be creating and destroying a lot of objects to make the calls.
For example
slow, lots of overhead:
myRecords = { cat, dog, mouse }
foreach record in myRecords
webservice check record
endforeach
faster:
myRecords = { cat, dog, mouse }
webservice check [myRecords] // array of records is passed instead of one by one
Debugging: The most likely risk is that somehow the task is not being disposed correctly - can you add this to your method to debug?
myTask = Task.Factory.StartNew(() =>
{
Console.Writeline("Task Started");
do{
checkMatches(tokenSrc.Token);
Thread.Sleep(10); // Some pause to stop your code from going as fast as it possibly can and putting your CPU usage to 100% (or 100/number of cores%)
}while(tokenSrc.IsCancellationRequested != true);
Console.Writeline("Task Stopped");
}
You might have to change that so it writes to a file or similar depending on if you have a console.
Then run it and make sure that only 1 task is being created.
I'm trying to learn those "new" keywords and tried to implement a simple async udp server.
public class UdpServerSync
{
private CancellationTokenSource _cts;
private CancellationToken _token;
private UdpClient _client;
public void Start()
{
Console.WriteLine("Start server");
_cts = new CancellationTokenSource();
_token = _cts.Token;
var ipAddress = IPAddress.Parse("192.168.0.25");
var ip = new IPEndPoint(ipAddress, 7070);
try
{
Task.Run(async () =>
{
using (_client = new UdpClient(ip))
{
while (!_token.IsCancellationRequested)
{
var receivedData = await _client.ReceiveAsync();
var msg = Encoding.ASCII.GetString(receivedData.Buffer);
// Process request e.g ProcessRequest(msg);
Console.WriteLine(msg);
}
}
}, _token).ConfigureAwait(false);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void Stop()
{
Console.WriteLine("Stop server");
if (_cts != null) _cts.Cancel();
}
And then use it like this (for testing purpose):
var server = new UdpServerSync();
server.Start();
await Task.Delay(5000);
server.Stop();
The above code is just a proof of concept, its not about code review. By a simple udp server I mean a while loop with a udpclient listening for udp messages and writing them to the console - no processing or error handling.
The reason for the Task.Delay is just because its a proof of concept of calling the server's start() and stop() methods.
To narrow down my questions:
1) if i was going to call the Start() and Stop() methods from e.g a WPF applicationĀ“s start button, should I use server.Start() or Task.Run ? I don't want to await the call since there's no way to know how long the user is going to want the server started.
2) in the server code "ProcessRequest(msg), if that was a void method in another library, should I use Task.Run() to execute it to avoid the server thread being blocked or is there a better way ?
3) When we do async/await, does the code in the await statement execute in a new thread from the thread pool ?
4) Can I specify that the UdpServer is a long running process or it doesn't matter to the thread pool ?
Hope my question is more clear now, thanks guys :)
1) if i was going to call the Start() and Stop() methods from e.g a WPF applicationĀ“s start button, should I use server.Start() or Task.Run ?
With the code you have now, you can just call Start (which calls Task.Run). IMO, the call to Task.Run is unnecessary. And the call to ConfigureAwait is definitely unnecessary since there's no await to configure.
I don't want to await the call since there's no way to know how long the user is going to want the server started.
But you probably do want to know about any exceptions. So, think about how to handle those. One solution is to save the returned Task as a property. Or, you could just await it (remember, it doesn't matter "how long" it runs, because it's an asynchronous wait).
2) in the server code "ProcessRequest(msg), if that was a void method in another library, should I use Task.Run() to execute it to avoid the server thread being blocked or is there a better way ?
There's no "server thread". But if ProcessRequest takes a long time, then you might want to consider using Task.Run so that your code will accept the next request while processing that one.
3) When we do async/await, does the code in the await statement execute in a new thread from the thread pool ?
No. I have an async intro on my blog that goes into more detail.
4) Can I specify that the UdpServer is a long running process or it doesn't matter to the thread pool ?
It doesn't matter.
I'm working on a system that involves accepting commands over a TCP network connection, then sending responses upon execution of those commands. Fairly basic stuff, but I'm looking to support a few requirements:
Multiple clients can connect at the same time and establish separate sessions. Sessions can last as long or as short as desired, with the same client IP able to establish multiple parallel sessions, if desired.
Each session can process multiple commands at the same time, as some of the requested operations can be performed in parallel.
I'd like to implement this cleanly using async/await and, based on what I've read, TPL Dataflow sounds like a good way to cleanly break up the processing into nice chunks that can run on the thread pool instead of tying up threads for different sessions/commands, blocking on wait handles.
This is what I'm starting with (some parts stripped out to simplify, such as details of exception handling; I've also omitted a wrapper that provides an efficient awaitable for the network I/O):
private readonly Task _serviceTask;
private readonly Task _commandsTask;
private readonly CancellationTokenSource _cancellation;
private readonly BufferBlock<Command> _pendingCommands;
public NetworkService(ICommandProcessor commandProcessor)
{
_commandProcessor = commandProcessor;
IsRunning = true;
_cancellation = new CancellationTokenSource();
_pendingCommands = new BufferBlock<Command>();
_serviceTask = Task.Run((Func<Task>)RunService);
_commandsTask = Task.Run((Func<Task>)RunCommands);
}
public bool IsRunning { get; private set; }
private async Task RunService()
{
_listener = new TcpListener(IPAddress.Any, ServicePort);
_listener.Start();
while (IsRunning)
{
Socket client = null;
try
{
client = await _listener.AcceptSocketAsync();
client.Blocking = false;
var session = RunSession(client);
lock (_sessions)
{
_sessions.Add(session);
}
}
catch (Exception ex)
{ //Handling here...
}
}
}
private async Task RunCommands()
{
while (IsRunning)
{
var command = await _pendingCommands.ReceiveAsync(_cancellation.Token);
var task = Task.Run(() => RunCommand(command));
}
}
private async Task RunCommand(Command command)
{
try
{
var response = await _commandProcessor.RunCommand(command.Content);
Send(command.Client, response);
}
catch (Exception ex)
{
//Deal with general command exceptions here...
}
}
private async Task RunSession(Socket client)
{
while (client.Connected)
{
var reader = new DelimitedCommandReader(client);
try
{
var content = await reader.ReceiveCommand();
_pendingCommands.Post(new Command(client, content));
}
catch (Exception ex)
{
//Exception handling here...
}
}
}
The basics seem straightforward, but one part is tripping me up: how do I make sure that when I'm shutting down the application, I wait for all pending command tasks to complete? I get the Task object when I use Task.Run to execute the command, but how do I keep track of pending commands so that I can make sure that all of them are complete before allowing the service to shut down?
I've considered using a simple List, with removal of commands from the List as they finish, but I'm wondering if I'm missing some basic tools in TPL Dataflow that would allow me to accomplish this more cleanly.
EDIT:
Reading more about TPL Dataflow, I'm wondering if what I should be using is a TransformBlock with an increased MaxDegreeOfParallelism to allow processing parallel commands? This sets an upper limit on the number of commands that can run in parallel, but that's a sensible limitation for my system, I think. I'm curious to hear from those who have experience with TPL Dataflow to know if I'm on the right track.
Yeah, so... you're kinda half using the power of TPL here. The fact that you're still manually receiving items from the BufferBlock in your own while loop in a background Task is not the "way" you want to do it if you're subscribing to the TPL DataFlow style.
What you would do is link an ActionBlock to the BufferBlock and do your command processing/sending from within that. This is also the block where you would set the MaxDegreeOfParallelism to control just how many concurrent commands you want to process. So that setup might look something like this:
// Initialization logic to build up the TPL flow
_pendingCommands = new BufferBlock<Command>();
_commandProcessor = new ActionBlock<Command>(this.ProcessCommand);
_pendingCommands.LinkTo(_commandProcessor);
private Task ProcessCommand(Command command)
{
var response = await _commandProcessor.RunCommand(command.Content);
this.Send(command.Client, response);
}
Then, in your shutdown code, you would need to signal that you're done adding items into the pipeline by calling Complete on the _pipelineCommands BufferBlock and then wait on the _commandProcessor ActionBlock to complete to ensure that all items have made their way through the pipeline. You do this by grabbing the Task returned by the block's Completion property and calling Wait on it:
_pendingCommands.Complete();
_commandProcessor.Completion.Wait();
If you want to go for bonus points, you can even separate the command processing from the command sending. This would allow you to configure those steps separately from one another. For example, maybe you need to limit the number of threads processing commands, but want to have more sending out the responses. You would do this by simply introducing a TransformBlock into the middle of the flow:
_pendingCommands = new BufferBlock<Command>();
_commandProcessor = new TransformBlock<Command, Tuple<Client, Response>>(this.ProcessCommand);
_commandSender = new ActionBlock<Tuple<Client, Response>(this.SendResponseToClient));
_pendingCommands.LinkTo(_commandProcessor);
_commandProcessor.LinkTo(_commandSender);
private Task ProcessCommand(Command command)
{
var response = await _commandProcessor.RunCommand(command.Content);
return Tuple.Create(command, response);
}
private Task SendResponseToClient(Tuple<Client, Response> clientAndResponse)
{
this.Send(clientAndResponse.Item1, clientAndResponse.Item2);
}
You probably want to use your own data structure instead of Tuple, it was just for illustrative purposes, but the point is this is exactly the kind of structure you want to use to break up the pipeline so that you can control the various aspects of it exactly how you might need to.
Tasks are by default background, which means that when application terminates they are also immediately terminated. You should use a Thread not a Task. Then you can set:
Thread.IsBackground = false;
This will prevent your application from terminating while the worker thread is running.
Although of course this will require some changes in your above code.
What's more you, when executing the shutdown method, you could also just wait for any outstanding tasks from the main thread.
I do not see a better solution to this.