Reputation: 775
First, apologize me for the title... I haven't found any suiting my single case :P
I need to download an INI
file to fill a Dictionary
first of all. For this, I have this class:
public class Properties : INotifyPropertyChanged
{
private Dictionary<string, string> _properties;
public Properties()
{
_properties = new Dictionary<string, string>();
}
public async void Load(string uri)
{
Stream input = await connection(uri);
StreamReader rStream = new StreamReader(input);
string line;
while((line = rStream.ReadLine()) != null)
{
if(line != "")
{
int pos = line.IndexOf('=');
string key = line.Substring(0, pos);
string value = line.Substring(pos + 1);
_properties.Add(key, value);
Debug.WriteLine("Key: " + key + ", Value: " + value);
}
}
Debug.WriteLine("Properties dictionary filled with " + _properties.Count + " items.");
}
public async Task<Stream> connection(string uri)
{
var httpClient = new HttpClient();
Stream result = Stream.Null;
try
{
result = await httpClient.GetStreamAsync(uri);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.HResult);
}
return result;
}
public string getValue(string key)
{
string result = "";
try
{
result = _properties[key];
}
catch(Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.HResult);
result = "Not found";
}
return result;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberName]string propertyName = "")
{
var Handler = PropertyChanged;
if (Handler != null)
Handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Mainly, the Dictionary
contains a Key
and a URL
to download XML
files to each page of the application.
The MainPage
, which is the one that is gonna be fill has this code:
public MainPage()
{
this.InitializeComponent();
//Properties dictionary filling
prop = new Properties();
prop.Load("URL");
tab = new Bars.TopAppBar();
bab = new Bars.BottomAppBar();
tABar = this.topAppBar;
actvt = this.Activity;
bABar = this.bottomAppBar;
//Constructor of the UserControl
act = new Home(this, prop);
}
The constructor of the UserControl
uses the MainPage
as a Callback
and the class Properties
to look for the URL to download the XML
file.
What happens is that, as Properties.Load()
is an asynchronous method, is called, then the remaining lines are executed and when the program finishes, then goes back to Load()
and fills the Dictionary
.
As the Home
constructor depends on a Value
of Properties
I get an Exception
.
I have tried to create async void
s assigning different priorities to force the program to run first one thing and then the remaining, but it hasn't worked either.
So, summarizing, I need to make sure that Properties
is filled in the first place, anyone knows how to do it?
Thanks in advance!
Upvotes: 0
Views: 119
Reputation: 473
Eva if you want to wait until the Load method is finished you have to change this method to return a Task.
public async Task LoadAsync(string uri)...
Better if you put your code in LoadedEventHandler of your page and make this method async. After that you will be able to await Properties.Load method.
If you want to call this method in constructor you can do it like this:
Task.Run(async () =>{
var task = p.LoadAsync().ConfigureAwait(false);
await task;
}).Wait()
But you have to be aware that deadlock can appear if in LoadAsync method will be await without disabled context switching (ConfigureAwait).
Upvotes: 2