J
JaedenRuiner
Guest
As we all know debugging multi-threaded applications is bear. It just sucks. However, I am very versed in manually handling threads, even devised my own thread pool that was more intelligent than the default .Net Thread Pool manager. This was several years ago, so the systems may have improved since then (likely).
I've also used the BackgroundWorker quite extensively, and as times change, languages evolve, i've started working primarily in the Task<> based async/await pattern. But there is a problem.
In order to "await' within a method, that method must be declared "async". However, when these methods get daisy-chained, so to speak, there is a lot - and i mean massive - amount of slippage.
For example, using the HttpClient system, the HttpContent has ReadAsStringAsync() which returns a Task<string>.
My method awaits said call, and thus must be defined 'async'. But the method calling it thus needs to await that method, and also must be called "async", and suddenly the UI gets to a point before any of these methods complete.
All the documentation says, that in a method when you "await" an async method, it allows the UI thread to continue. This may have been updated, but it should really read the "parent thread" to continue. When the async operation is complete it returns to the "await" line, and executes lines after that. However, if inside the "async" method you are awaiting another method, this nesting effect causes the the first async to complete and continue before the nested one is done.
I have tried many ways around this, but executing a Task<> based method without the "await" command, always, and i mean ALWAYS, deadlocks my program. the Task<string>.Result never returns from it and the program hangs. So when i have a situation of an async method that needs to be awaited, how do I get the parent async method to await as well?
protected override async void OnLoad(object sender, EventArgs e)
{
this.Items = await this.LoadItems();
this.EndUpdate();
}
private async Task<List<ItemObject>> LoadItems()
{
using (HttpClient client = new HttpClient())
{
url = Whatever.CreateRequest();
HttpResponseMessage message = await client.GetAsync(url);
string response = await message.Content.ReadAsStringAsync();
return new List<ItemObject>(Whatever.ParseResponse<ItemObject>(response));
}
}
private void EndUpdate()
{
comboBox1.DataSource = this.Items;
ItemObject item = comboBox1.SelectedItem as ItemObject;
// item is ALWAYS NULL HERE because Items.Count == 0, they aren't loaded yet
}
in that paltry example, you see that the LoadItem returns a Task<ItemObject> but inside that method it also await two calls to the HttpClient and HttpContent classes. the moment the code executions hits the nested await, the await in OnLoad() is resolved, and EndUpdate executes before the data is loaded.
Trying to not use the await, i get a Task back instead of the inner result type that the black-box of the Task system overlooks with awaiting. When I access Task.Result the program locks.
How do i fix this? What is the sequence for executing async methods so that no matter where the await lies, execution DOES NOT CONTINUE in that method until that full path of "await" calls is resolved?
Thanks
Jaeden "Sifo Dyas" al'Raec Ruiner
(It seems that ever "await" call spawns a new thread. but since i can't retrieve Task data without the "await" i'm spawning 2,3, even 4 threads for a single operation. sometimes, i want to control when the thread is created, and all executions within that thread should be synchronous to that thread. so if "await" spawns a thread, i need to be able to access Task Results from within the first async operation.)
"Never Trust a computer. Your brain is smarter than any micro-chip."
PS - Don't mark answers on other people's questions. There are such things as Vacations and Holidays which may reduce timely activity, and until the person asking the question can test your answer, it is not correct just because you think it is. Marking it correct for them often stops other people from even reading the question and possibly providing the real "correct" answer.
Continue reading...
I've also used the BackgroundWorker quite extensively, and as times change, languages evolve, i've started working primarily in the Task<> based async/await pattern. But there is a problem.
In order to "await' within a method, that method must be declared "async". However, when these methods get daisy-chained, so to speak, there is a lot - and i mean massive - amount of slippage.
For example, using the HttpClient system, the HttpContent has ReadAsStringAsync() which returns a Task<string>.
My method awaits said call, and thus must be defined 'async'. But the method calling it thus needs to await that method, and also must be called "async", and suddenly the UI gets to a point before any of these methods complete.
All the documentation says, that in a method when you "await" an async method, it allows the UI thread to continue. This may have been updated, but it should really read the "parent thread" to continue. When the async operation is complete it returns to the "await" line, and executes lines after that. However, if inside the "async" method you are awaiting another method, this nesting effect causes the the first async to complete and continue before the nested one is done.
I have tried many ways around this, but executing a Task<> based method without the "await" command, always, and i mean ALWAYS, deadlocks my program. the Task<string>.Result never returns from it and the program hangs. So when i have a situation of an async method that needs to be awaited, how do I get the parent async method to await as well?
protected override async void OnLoad(object sender, EventArgs e)
{
this.Items = await this.LoadItems();
this.EndUpdate();
}
private async Task<List<ItemObject>> LoadItems()
{
using (HttpClient client = new HttpClient())
{
url = Whatever.CreateRequest();
HttpResponseMessage message = await client.GetAsync(url);
string response = await message.Content.ReadAsStringAsync();
return new List<ItemObject>(Whatever.ParseResponse<ItemObject>(response));
}
}
private void EndUpdate()
{
comboBox1.DataSource = this.Items;
ItemObject item = comboBox1.SelectedItem as ItemObject;
// item is ALWAYS NULL HERE because Items.Count == 0, they aren't loaded yet
}
in that paltry example, you see that the LoadItem returns a Task<ItemObject> but inside that method it also await two calls to the HttpClient and HttpContent classes. the moment the code executions hits the nested await, the await in OnLoad() is resolved, and EndUpdate executes before the data is loaded.
Trying to not use the await, i get a Task back instead of the inner result type that the black-box of the Task system overlooks with awaiting. When I access Task.Result the program locks.
How do i fix this? What is the sequence for executing async methods so that no matter where the await lies, execution DOES NOT CONTINUE in that method until that full path of "await" calls is resolved?
Thanks
Jaeden "Sifo Dyas" al'Raec Ruiner
(It seems that ever "await" call spawns a new thread. but since i can't retrieve Task data without the "await" i'm spawning 2,3, even 4 threads for a single operation. sometimes, i want to control when the thread is created, and all executions within that thread should be synchronous to that thread. so if "await" spawns a thread, i need to be able to access Task Results from within the first async operation.)
"Never Trust a computer. Your brain is smarter than any micro-chip."
PS - Don't mark answers on other people's questions. There are such things as Vacations and Holidays which may reduce timely activity, and until the person asking the question can test your answer, it is not correct just because you think it is. Marking it correct for them often stops other people from even reading the question and possibly providing the real "correct" answer.
Continue reading...