Hello everyone!
Sadly I am no where the programmer I once was. In what seems a previous lifetime I was a C/C++ programmer professionally for a large AV company. After the dotcom crash and some tough personal decisions I chose to join the military, and subsequently was wounded receiving a TBI in the process.
Now I am trying to get back to my roots in programming again, but from atrophy and TBI I think I am lucky to remember that I can use a semaphore to block access to a block of code (again I actually could be wrong here, a semaphore could actually be an alcoholic beverage served with a tiny umbrella for instance).
I am trying to move forward using the following assumptions. If anyone spots inconsistencies, or incorrect thoughts please let me know!
Main / UI thread = the thread that is the "MessagePump" in C/C++ programming, aka Root thread.
await
= this function will be a Task<>
function and to handle the returned var as a variable which could spontaneously change (when the async thread completes and the data is in it's "Stable" state.
ConfigureAwait(true)
= This call will at some point need to have access to the screen or UI so let the thread it spawns come back to the main UI thread (Let's say the function want's to call DisplayAlert
, or directly modify some control in the UI)
ConfigureAwait(false)
= This thread will go do something off on it's own. It will never come back to the main (UI) thread. Once this function is done it's done. A one way street more or less.
Semaphore
= A call to begin a process that can only run x number of times concurrently. If two threads come to the door, only x number can enter, the others have to wait (or be configured to just JMP
past this and continue on their merry way)
Mutex
= Starting line for a race, do not execute the code behind this wall until some condition is met and then release the dogs of war, (or the kittens of spring as it may be...)
Using this mindset I am assuming the following scenarios.
I have a report I want to dump to an excel file, the data is in the DB.
await CreateExcelReport(<"Conditional information to generate the report with">).ConfigureAwait(false);
In this example I expect that the CreateExcelReport function will execute using what I passed as an argument to generate my report, the thread will never come back, and more importantly CANNOT come back with information to the main thread, it is in essence "Fire and forget".
This last example is one I am struggling with, because in my code I see inconsistent behavior at times, with this being the correct idea, and other times it seems to now want to work.
I have some data that needs to be looked up in the database and reported to the screen
string PersonsFirstName = await LookUpRecordsByPK(<"database PK's to lookup">).ConfigureAwait(true);
In this example the LookUpRecordByPK would be something like this
public static async Task<string> LookUpRecordByPK (int id) { var connection = ConnectToDB(); // I am using ConfigureAwait(False) here because this call should execute as quickly as possible. var p = new ObservableCollection<People>(await connection..QueryAsync<People>("SELECT * FROM People WHERE Id=?", id).ConfigureAwait(false); if (p?.Count > 0) return p?[0].FirstName; else return null; }
I have other issues (well who doesn't?) but this is probably the best starting place I can think of...
Thanks everyone!
You are on the right way. But the last code example have some issues.
public static async Task<string> LookUpRecordByPK (int id) { var connection = ConnectToDB(); // I am using ConfigureAwait(False) here because this call should execute as quickly as possible. var p = new ObservableCollection<People>(await connection..QueryAsync<People>("SELECT * FROM People WHERE Id=?", id).ConfigureAwait(false); if (p?.Count > 0) return p?[0].FirstName; else return null; }
Do not create so expensive collections like ObservableCollection without the need. If you want to just return a values use an array. Finally, you are searching for a one item in DB. Why do you need a collection?
Often you can use extension methods like ToArray, ToList, First(), etc in the queries. I suppose the method QueryAsync returns something like IEnumerable. So, you can return an array or an interface.
Often you can just return a Task.
So, improved code variant:
public static async Task<IEnumerable<People>> LookUpRecordByPK (int id) { var connection = ConnectToDB(); return connection.QueryAsync<People>($"SELECT * FROM People WHERE Id={id}"); }
or if you need to return just a string:
public static async Task<string> LookUpRecordByPK (int id) { var connection = ConnectToDB(); //I don't see any complex things after this query, so you don't need a ConfigureAwait(false) in my opinion. People people = (await connection.QueryAsync<People>($"SELECT * FROM People WHERE Id={id}").)FirstOrDefault(); return people?.FirstName; }
Answers
It isn't clear what your question is. Can you summarize?
You are on the right way. But the last code example have some issues.
Do not create so expensive collections like ObservableCollection without the need. If you want to just return a values use an array. Finally, you are searching for a one item in DB. Why do you need a collection?
Often you can use extension methods like ToArray, ToList, First(), etc in the queries. I suppose the method QueryAsync returns something like IEnumerable. So, you can return an array or an interface.
Often you can just return a Task.
So, improved code variant:
or if you need to return just a string:
I will definitely look at using arrays over obsservableCollections. I can see how it would have some serious overhead, I have a bunch of places where I send the lists and arrays to screen controls so I tended to use the obs-collections. I need to recheck my code and streamline the use of them.
I'll take a look at using the IEnumeral method, it looks like the better slimmer code to work with.
Thanks again!