I have a few objectives, which lead to this combination of code:
- Call some API functions async, so they run parallel and don't freeze the UI
- Show a
progressBar
in the meantime as the comboBoxes get filled with the API-data
I would like to keep my tasks in a List
or other data structure in order to count them and assign this count value to the Maximum
property in my progressBar
.
public async void retrieveAPIData()
{
// hide everything except the progressbar
var controls = this.Controls.Cast<Control>().Where(
control => !control.Equals(progressBar));
foreach (var control in controls)
{
control.Visible = false;
}
// handler for when the progress gets Report-ed (Report function)
var progress = new Progress<int>(percent =>
{
progressBar.Value += percent;
});
// api singleton
var proErp = ProERP.Instance;
// attempt at a List that combines tasks to their comboBox through a data class
List<ControlFiller> tasks = new List<ControlFiller>()
{
new ControlFiller()
{
task = proErp.GetColumns(progress),
ComboBox = squareHollowSection
},
new ControlFiller()
{
task = proErp.GetProfiles(progress),
ComboBox = typeOfProfile
},
};
// most important reason to store the tasks in a List, to count them to know how
// many steps there will be
progressBar.Maximum = tasks.Count;
//var columnsTask = proErp.GetColumns(progress);
//var profilesTask = proErp.GetProfiles(progress);
//this.squareHollowSection.DataSource = await columnsTask;
//this.typeOfProfile.DataSource = await profilesTask;
// The design time errors occur here!
foreach (var task in tasks)
{
task.ComboBox.DataSource = await task.task;
}
// To not hide the progressBar too fast for development
Thread.Sleep(2000);
// tasks finished
progressBar.Visible = false;
// show the other Controls again
foreach (var control in controls)
{
control.Visible = true;
}
}
In the task I call (example from Profile
):
public async Task<List<Profile>> GetProfiles(IProgress<int> progress)
{
var request = new RestRequest("Profile", Method.GET);
IRestResponse response = await client.ExecuteAsync(request);
progress.Report(1);
return new JsonDeserializer().Deserialize<List<Profile>>(response);
}
ControlFiller class:
internal class ControlFiller
{
public Task task;
public ComboBox ComboBox;
}
However this does not work as I use Task
in ControlFiller
which returns void, I however can neither return as specific class as it would only work for 1 task or Object as the Task Generic of Task<Object>
cannot be converted implicitly. Is there a way to create a list of tasks to count, let them run and assign their awaited value to a DataSource
for my form?
The linked answer is not even helpful as I want to assign the returned values dynamically, now I need to know which value sits in which index.
edit:
Even with a common foreach loop I cannot await the values as my DataStructure will cast(?)
Task<Column>
and Task<Profile>
to a Task
that doesn't return anything (void). Is there a way to
- Count the Tasks (not necessarily in a Data Structure).
- If they are added to a Data Structure, await their values and assign it to their respective ComboBox.
Self answer (which I cannot post because the question is closed) I moved the assigning of the ComboBox values to the Task itsels, than I don't need the return value.
public async void retrieveAPIData()
{
var controls = this.Controls.Cast<Control>().Where(control => !control.Equals(progressBar));
foreach (var control in controls)
{
control.Visible = false;
}
var progress = new Progress<int>(percent =>
{
progressBar.Value += percent;
});
var proErp = ProERP.Instance;
var GetColumnsTask = proErp.GetColumns(progress, squareHollowSection);
var GetProfileTask = proErp.GetProfiles(progress, typeOfProfile);
ArrayList list = new ArrayList()
{
GetColumnsTask, GetProfileTask
};
await GetColumnsTask;
await GetProfileTask;
progressBar.Maximum = list.Count;
Thread.Sleep(2000);
progressBar.Visible = false;
foreach (var control in controls)
{
control.Visible = true;
}
}
Task
public async Task<List<Profile>> GetProfiles(IProgress<int> progress, ComboBox comboBox = null)
{
var request = new RestRequest("Profile", Method.GET);
IRestResponse response = await client.ExecuteAsync(request);
progress.Report(1);
var data = new JsonDeserializer().Deserialize<List<Profile>>(response);
comboBox.DataSource = data;
return data;
}
>` and `Task
– online Thomas Jan 19 '21 at 17:06>` respectively
>`?
– Theodor Zoulias Jan 20 '21 at 08:00