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);
}
}
Related
Simply I want to make an external call to external api which has SenMessageAsync(string message) method and i need to return my client Ok() without waiting it to finish. But on the backend side I need to response of SendMessageAsync() method for continue some process. I mean somehow I need to await it.
Example
try
{
//...
var response = await SendMessageAsync("test"); //dont wait the response, return Ok()
//do something with response
}
catch(MyException ex)
{
//Log
}
catch(Exception ex)
{
//Log
}
Update:
I am updating with one solution I found. Task.Run() (which called fire and forget). Maybe it helps someone. Thanks for answers.
Solution 1:
_ = Task.Run(() => SendMessageAsync(), task =>
{
//We can have exception here if SendMessageAsync() fails
var exception = task.InnerException.Exception;
//Log the exception
}, TaskContinuationOptions.OnlyOnFaulted)
You need a basic distributed architecture, as described on my blog. In summary:
A durable queue. Serialize the work to be done into this queue (e.g., { "operation" = "SendMessage", "data" = "test" }).
A separate backend processor that reads from that queue and does the actual work (e.g., SendMessageAsync(message.data)).
Your backend processor can await the call to SendMessageAsync and then do further processing.
You can use the Task.Run method to run the SendMessageAsync method asynchronously on a separate thread. You can then return Ok() to the client immediately, while the SendMessageAsync method continues to run in the background. To wait for the result of the SendMessageAsync method, you can use the await keyword within the Task.Run method.
Here's an example:
public async Task<IActionResult> MyAction()
{
// Return Ok() immediately to the client
_ = Task.Run(async () =>
{
// Run SendMessageAsync asynchronously on a separate thread
var result = await SendMessageAsync("My message");
// Continue processing using the result of SendMessageAsync
// ...
});
return Ok();
}
I have a scenario where I have x amount of queries and I want to run each query in a different thread.
My problem is the Http GetAsync method only works when it returns a Task, I tried to return a void but it did not work. But to create multiple threads I need to return a void.
public static async Task threadAsync(string query)
{
var watch = System.Diagnostics.Stopwatch.StartNew();
try
{
watch.Restart();
HttpResponseMessage response = await client.GetAsync(query);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
watch.Stop();
string logData += $"Execution Time: {watch.ElapsedMilliseconds} ms, ";
watch.Reset();
var data = JObject.Parse(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine("\nException Caught!");
Console.WriteLine("Message :{0} ", e.Message);
}
}
I have multiple methods in Threads class with different queries. I tried using GetAwaiter().GetResult(), but that also did not work. How can I use run each query in a different thread?
public class Threads
{
public static void thread1Create()
{
string query = "SOMEQUERY";
threadAsync(query).GetAwaiter().GetResult()
}
};
want to run each query in a different thread.
Why?
You really need to learn how windows works internally and what completion ports are. Async methods run on NO thread - they just get called into a thread back when they are done. This is based on the windows network model actually - NOT HAVING THREADS WHILE IT WORKS.
My problem is the Http GetAsync method only works when it returns a Task, I
tried to return a void
Given that GET Returns something in the task, that would be utterly useless.
Your problem is this:
HttpResponseMessage response = await client.GetAsync(query);
There is no requirement to AWAIT immediately. Start all the async get operations, then start awaiting them.
Really learn basics - you USE async, but you THINK in threads still and thus you do not understand what the async model really gives you. The result is a cargo cult like programming totally nullifying the advantages of async, and now asking how to then regain them via threads.
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.
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 that communicates with a serial port. I am trying to make it so it doesn't freeze the UI when a series of reads are performed. I initially used a thread, but in the long run that isn't going to work well (the code is much more complicated than what is below). I am trying to figure out async/await, and here is what I have tried so far.
I have a click handler and related methods (details, including parameters to some of the methods, removed for simplicity) as follows:
private void cmdOpenModPort_Click(object sender, EventArgs e) {
// stuff
CheckBoardsAsync();
// stuff
}
private async void CheckBoardsAsync() {
// Read from a serial port with different settings.
for (byte iTryAdrs = 125; iTryAdrs <= 144; iTryAdrs++) {
ushort[] registers = await mt.ReadRegistersChkSeeBrdAsync(iTryAdrs);
if (registers != null) {
// Update UI based on registers
} else {
// Update UI
}
}
}
public async Task<ushort[]> ReadRegistersChkSeeBrdAsync(byte b) {
// can't await because the method is not async.
return ReadRegistersChkSeeBrd(b);
}
public ushort[] ReadRegistersChkSeeBrd(byte b) {
try {
// read from serial port. NOT an asynchronous method and it is
// calling a method from a package so I cannot control this.
return master.ReadHoldingRegisters(b);
} catch (Exception) {
return null;
}
}
This doesn't work because the click handler doesn't finish until CheckBoardsAsync finishes. I want the call to CheckBoardsAsync to be asynchronous, but that method makes a series of asynchronous calls and doesn't itself need to return anything, so there isn't a value to wait for. Since it doesn't return anything, I can't await it.
So what is the proper way to deal with this? My understanding is that I should not use threads in this case because I am waiting for I/O, and there is hardly any computation. So this seems like the correct approach. Do I just fake it and have the CheckBoardsAsync return something I don't care about? That seems weak.
I hope I have been clear enough.
You should be getting a warning for having a async method that has no await calls in it. Marking a method as async doesn't automatically make it asynchronous, it just allows the use of the await keyword. Here you have CPU bound work, no IO bound work, so what you want to do is perform that work in another thread (which can be done using Task.Run) and then asynchronously wait on that.
The change is easy enough, just remove ReadRegistersChkSeeBrdAsync entirely and replace:
ushort[] registers = await mt.ReadRegistersChkSeeBrdAsync(iTryAdrs);
with
ushort[] registers = await Task.Run(() =>
mt.ReadRegistersChkSeeBrd(iTryAdrs));
It would also be better practice to remove the CheckBoardsAsync method entirely and have the body of that method simply be the body of cmdOpenModPort_Click. (Or, for that matter, just attach CheckBoardsAsync as the click handler.)
You need to make it return Task (not Task<T>).
You can then await it even though it doesn't return a value.