I've got a WPF application that needs to process a list of items asynchronously. As of right now, I loop through the list of items, and for each one, I await the operation. Everything seems to be fine 90% of the time. The other 10% of the time, I'm getting timeout errors (has exceeded the allotted timeout of 00:01:00). What's weirding me out is that the operations seem to of completed on the backend. Everything looks fine in the database. No errors on the server side. I'm only getting this timeout error on my WPF client.
I'm awaiting my WCF call on each one, so it isn't timing out on the individual call. Each individual call doesn't take long (maybe a few seconds), however the entire operation could take up to a minute or so.
private async void MyClickEvent(object sender, RoutedEventArgs e){
await HandleProcessing(MyListOfIds);
}
private async Task HandleProcessing(List<int> Ids)
{
foreach (var id in Ids)
{
try
{
// This function makes 2 wcf calls. both 2 are awaited
int i = await MyFunctionThatMakesWCFCalls(id);
}
catch (Exception e)
{
//log error
}
}
}
private async Task<int> MyFunctionThatMakesWCFCalls(int id){
bool success = await _serviceClient.MyCall(id);
if (success){
return await _serviceClient.MySecondCall(id);
}
return 0;
}
So, I suppose each iteration in the loop could potentially take a few seconds (sometimes up to 10). Like I said, even though I get the exception in my log, the data in the backend seems to all be there. I'm not sure how to get around this false positive error. Any help would be greatly appreciated.
Related
I'm communicating with a custom external device, and this device requires when I send data, I must send the same data once again, between 10 and 100 milliseconds (send the data twice 10-100 ms interval).
Basically it's working very well to send the data, but the second sending is between 500 - 800 milliseconds, so I must decrease it.
I using Plugin.BLE
...
public async Task WriteCharacteristics(byte value)
{
try
{
byte[] data = {value};
await Service.GetCharacteristicsAsync().ContinueWith(async task =>
{
Characteristics = task.Result;
await Characteristics.First().WriteAsync(data).ContinueWith(async t1 =>
{
await Characteristics.First().StartUpdatesAsync();
});
});
}
catch (Exception e)
{
Debug.WriteLine("********* Failed to get ReadCharacteristics: " + e.Message);
}
}
...
and when I call:
...
_ = ble.WriteCharacteristics((byte)value).ContinueWith(_ =>
{
Thread.Sleep(10);
ble.WriteCharacteristics((byte)value).Wait();
});
...
I tried to call the function twice, as parallel, but that solution not good.
As you see when I call, it waits 10 milliseconds, and want to send the data again. Is there any workaround to solve this problem?
One reason for the long delay between write operations could be the writeType. There are two types, writeWithResponse and writeWithoutResponse. The first is the safer method because you will receive a confirmation if your message was sent correctly. This obviously restricts data throughput.
Setting the writeType to writeWithoutResponse could work in your case. This issue on github shows the correct way:
Characteristics.WriteType = Plugin.BLE.Abstractions.CharacteristicWriteType.WithoutResponse;
I see two issues that can be improved:
As mentioned by JonasH in a comment, don't use async/await and ContinueWith together. await is sufficient to suspend your code until an async Task completes.
Re-use the "setup" of the communications, so that only the final call needs to be done twice.
I'm not familiar with that plugin (looked at its docs just now, to confirm the basic approach), so this code may need some adjustment, but hopefully this will be a starting point:
public async Task WriteByteTwice(byte value)
{
try
{
// Plug-in docs say WriteAsync call should be on MAIN THREAD.
if (!Xamarin.Essentials.MainThread.IsMainThread)
throw new InvalidProgramException("WriteByteTwice must be called from MainThread");
byte[] data = {value};
Characteristics = await Service.GetCharacteristicsAsync();
// Send data first time.
await Characteristics.First().WriteAsync(data);
await Characteristics.First().StartUpdatesAsync();
await Task.Delay(10);
// Send data again.
await Characteristics.First().WriteAsync(data);
await Characteristics.First().StartUpdatesAsync();
}
catch (Exception e)
{
Debug.WriteLine("********* Failed to get ReadCharacteristics: " + e.Message);
}
}
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.
I need to a background long running thread from the asp.net application.
BTW,the method fetches something from external data source period and maybe exception happens, I provide some ways to fullfill this task, please advice which way is best, please advice if there is better way.
Way1=Looping when exception happens.
static void LongRunningMethod()
{
do
{
try
{
//fetch something from external period and maybe exception happens.
Thread.sleep(100000);
}
catch(Exception ex)
{
//log exception..
}
} while (true);
}
Way2=Running the following method period by something like timer, and open a new thread when exception happens.
static void LongRunningMethod()
{
try
{
//fetch something from external period and maybe exception happens.
Thread.sleep(100000);
}
catch(Exception ex)
{
//log exception..
Thread T2 = new Thread(LongRunningMethod);
T2.Start();
}
}
Way3=Call itself when exception happens.
static void LongRunningMethod()
{
try
{
//fetch something from external period and maybe exception happens.
Thread.sleep(100000);
}
catch(Exception ex)
{
//log exception..
LongRunningMethod();
}
}
I will use none of the three. In fact, I seldom build interval tasks base on ASP.NET because:
1. The start of the task is out of control
Based on ASP.NET the task has to be started/registered on Application_Start method, which is triggered by the first request, that means your tasks is started when the first request comes. Theoretically it can be long time after your application is deployed.
2. The end of the task is out of control
The web servers (thinking IIS) can be configured as recycle-on-demand (AFAIK this is the default behavior). That is, your thread may be killed when executing. Under most circumstances you need to deal with the persistence of your tasks and states, and add retrying codes and etc... That's a nightmare!
For me it's a better idea to use a windows service, or the task scheduler function of windows, the latter is even easier because you don't need to write a timer or interval call codes. It's more stable, less code, and friendly logs in the event viewer! That's really make everything easier.
I like to use System.ComponentModel.BackgroundWorker:
static BackgroundWorker looper = new BackgroundWorker();
static bool isRunning = true;//you can set this to false when closing
public static void initialize(){
looper.DoWork+= doLoop;
looper.RunRunWorkerAsync();
}
private static void doLoop(object sender, DoWorkEventArgs e){
while(isRunning){
//do looping code
System.Threading.Thread.Sleep(5000);
if(!isRunning)
break;
}
}
PS - sorry for weird spacing - I edited this directly in the code window.
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 have an application which handles data from text file - it reads a line from the file then handles it and then puts a result in another file. After handling one row it handles the next one until the whole file is done. Some rows from the file is very time-consuming for handling. So I decided to put handling-logic in separate thread and if handling takes longer then 10 sec. I kill the thread. So my code is like this:
public class Handler
{
public void Handle(string row)
{
// Perform handling
}
}
public class Program
{
private static bool HandleRow(string row)
{
Task task = new Task(() => new Handler().Handle(row));
task.Start(); // updated
var waitResult = task.Wait(timeout); // timeout is 10 sec.
if(waitResult == false || task.IsFaulted)
return false;
return true;
}
public static void Main()
{
foreach(var row in GetRowsToHandle())
HandleRow(row);
}
}
but somehow when running the program I get out of memory exception. It seems that memory is not released properly.
Does anyone know why memory leaks might happen?
UPDATED
I forgot to include task.Start() in my code sniffer. Now I put it there
Task is Disposable : task.Dispose();
Your 10s timeout only times out the task. It doesn't stop Handle() from executing (if indeed it ever starts - I can't see a Start there). It just means you locally see a timeout on task.
Also, it depends in part on what GetRowsToHandle() does - does it return a non-buffered sequence, or is it a list, etc.
While Task does support cancellation, this requires co-operation from the implementation. To be honest, since you aren't doing anything async you might be better off just handling your own "have I taken too long" basic timeout in Handle(). A thread-abort (the other option) is not to be recommended.