I have the following code that is meant to fetch data from a REST service (the Get(i)
calls), then populate a matrix (not shown; this happens within addLabels()
) with their relationships.
All of the Get()
calls can run in parallel to each other, but they must all be finished before anything enters the second loop (where, once again, the calls can run in parallel to each other). The addLabel()
calls depend on the work from the Get()
calls to be complete.
** To anyone stumbling across this post, this code is the solution:**
private async void GetTypeButton_Click(object sender, RoutedEventArgs e)
{
await PokeType.InitTypes(); // initializes relationships in the matrix
var table = PokeType.EffectivenessMatrix;
// pretty-printing the table
// ...
// ...
}
private static bool initialized = false;
public static async Task InitTypes()
{
if (initialized) return;
// await blocks until first batch is finished
await Task.WhenAll(Enumerable.Range(1, NUM_TYPES /* inclusive */).Select(i => Get(i)));
// doesn't need to be parallelized because it's quick work.
foreach(PokeType type in cachedTypes.Values)
{
JObject data = type.GetJsonFromCache();
addLabels(type, (JArray)data["super_effective"], Effectiveness.SuperEffectiveAgainst);
addLabels(type, (JArray)data["ineffective"], Effectiveness.NotVeryEffectiveAgainst);
addLabels(type, (JArray)data["no_effect"], Effectiveness.UselessAgainst);
}
initialized = true;
}
public static async Task<PokeType> Get(int id);
As the code is currently written, the InitTypes()
method attempts to enter both loops simultaneously; the cachedTypes
dictionary is empty because the first loop hasn't finished populating it yet, so it never runs and no relationships are constructed.
How can I properly structure this function? Thanks!