>Salve 0v3rCl0ck e grazie della risposta.
>
>Si come indicato nel primo 3d sto utilizzando restsharp su visual
>studio 2013 per wp8.
si scusami non avevo letto bene il 3d, usi restsharp e così intanto ho scoperto come mai non ti da eccezione la callback nell'impostare la textbox, perchè guardando il codice di restsharp ho notato che sfruttano syncronization context, e lo abilitano di default per windows phone, ed è solo per questo che non ti da errore, altrimenti devi sapere che una normale esecuzione asincrona ti chiamerebbe il delegato/callback su un altro thread parallelo a quello principale, e appena tenti di impostare qualsiasi cosa sia legata alla GUI, ti da eccezione perchè sulla gui non è previsto l'accesso asincrono, ma ogni comando diretto alla gui deve essere smistato da un solo thread.
>
>Ora vedo di leggermi qualcosa riguardo la task programming e
>provare ad implementare la tua soluzione, potresti cortesemente
>spiegarmi l'esistenza dei 2 main?
i due main non c'entrano con il tuo programma, me li sono fatti per provare in un progetto console, il succo della questione sta nel fatto che se vuoi creare un metodo che al suo interno chiami una funzione asincrona, hai due possibilità:
1 - creare il metodo a sua volta asincrono, per mantenere lo stesso flusso di esecuzione, e fare capire a chi chiama il metodo che si deve aspettare un esecuzione asincrona, per cui dovrà sapere come sincronizzarsi ad esso, o con i task o con un delegato di callback o anche con eventi (se invece che un metodo fosse una classe intera, vedi il backgroundWorker che lavora ad eventi)
2 - creare il metodo sincrono, ma anche qui rispettando il flusso che ci si aspetta da un metodo sincrono, e cioè al termine dell'esecuzione mi deve garantire che il risultato sia pronto e leggibile, e per questo dovresti bloccare l'esecuzione del thread corrente, aspettando la risposta dal RestRequest, a questo punto sfruttando la chiamata sincrona Execute invece che ExecuteAsync, oppure sincronizzando sul thread corrente l'ExecuteAsync.
ovviamente nel tuo caso di wp8 hai optato per l'esecuzione asincrona, e hai fatto bene, perchè se non sbaglio anche su wp8 come per le store app di win8, l'esecuzione delle applicazioni è controllato, e non è possibile bloccare il thread principale per più di x secondi, altrimenti l'applicazione viene killata dal sistema operativo.
Ho controllato meglio RestSharp e ha anche l'interfaccia a task, quindi vediamo di sfruttare quella...
Detto questo vediamo di ripartire dal metodo asincrono che volevi creare per potere riutilizzare parti di codice:
public class Connessione
{
public async Task<Dati> GetAsync()
{
RestRequest request = new RestRequest("url servizio");
request.Method = Method.GET;
RestClient client = new RestClient();
var response = await client.ExecuteTaskAsync(request);
Dati dati = JsonConvert.DeserializeObject<Dati>(response.Content);
return dati;
}
}
nel metodo ExecuteTaskAsync i ragazzi della RestSharp, hanno già implementato quello che ti avevo postato precedentemente, facendo in modo di ritornare un Task, che poi ti da la possibilità di utilizzare async/await, che sono comodissimi per sincronizzarsi all'esecuzione di codice asincrono, perchè come vedi, in pratica, il codice a prima vista non cambia praticamente niente da un codice sincrono, se non che devi aggiungere async alla dichiarazione del metodo e await davanti ai metodi che lanci. Poi ovviamente ci sono importanti considerazioni che stanno alla base di tutto questo, ma ti invito a leggere un po' di documentazione sulla task programming sull'msdn.
Una volta creato il tuo metodo async è possibile richiamarlo esattamente come abbiamo fatto per ExecuteTaskAsync (sui tuoi metodi non aggiungere Task, la naming convention di default dice di aggiungere solo Async in fondo ai metodi, loro hanno dovuto aggiungere TaskAsync, per retrocompatibilità del loro stesso codice dove avevano già un interfaccia che ritornava Async però chiedendo il delegato invece che tornare il Task):
var connessione = new Connessione();
var dati = await connessione.GetAsync();
tbkNome.Text = dati.Nome;
tbkStato.Text = dati.Stato;
poi dato che questo codice da quello che ho capito devi lanciarlo sia in apertura della form che successivamente alla pressione di un pulsante, tanto vale crearci un metodo (sempre async) in comune per entrambi i caricamenti:
public async Task LoadDataAsync()
{
var connessione = new Connessione();
var dati = await connessione.GetAsync();
tbkNome.Text = dati.Nome;
tbkStato.Text = dati.Stato;
}
che poi verrà chiamato all'interno del comando lanciato dal pulsante:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await LoadDataAsync();
}
e nel costruttore, facendo particolare attenzione a salvarsi da parte un riferimento al task di inizializzazione, che potrebbe servire a chi crea la form/window, per sincronizzarsi al caricamento dei dati della form stessa:
infine ti allego il codice per intero:
>private void btStatoDisp_Click(object sender, RoutedEventArgs
>e)
> {
>RestRequest request = new RestRequest(url servizio);
> request.Method = Method.GET;
>
> RestClient client = new RestClient();
> client.ExecuteAsync(request, response =>
> {
>
>Dati dati = JsonConvert.DeserializeObject<Dati>(response.Content);
> tbkNome.Text = Dati.Nome;
>
> });
>
> tbkStato.Text = Dati.Stato;
> }
>
qui sbagli perchè "tbkStato.Text = Dati.Stato;" deve rimanere dentro alla callback, altrimenti dati, non sarà valorizzato subito, sempre per il discorso dell'asincronia dell'esecuzione. Inoltre non devi usare le statiche sulle proprietà di Dati, devi leggere dall'oggetto creato dal deserializzatore:
client.ExecuteAsync(request, response =>
{
Dati dati = JsonConvert.DeserializeObject<Dati>(response.Content);
tbkNome.Text = dati.Nome;
tbkStato.Text = dati.Stato;
});
>La mia classe Dati è cosi:
>
>
>namespace Test
>{
> public class Dati
> {
>
> [JsonProperty("nome")]
> public static string Nome { get; set; }
>
> [JsonProperty("stato")]
> public static string Stato { get; set; }
> }
>}
>
non fare mai proprietà static sugli oggetti che rappresentano entità, perchè altrimenti non riesci ad istanziarle, di fatto quell'oggetto così com'è, quando è istanziato, creerebbe un oggetto vuoto, perchè la definizione della classe contiene solo 2 proprietà statiche, e nemmeno una non statica, statica vuol dire che ne esiste una per tutta la durata dell'applicazione, e non va bene per quello che devi fare, quindi la classe dovrà essere come quella che ti ho postato sopra:
public class Dati
{
[JsonProperty("nome")]
public string Nome { get; set; }
[JsonProperty("stato")]
public string Stato { get; set; }
}
un ultimo appunto... restsharp prevede anche di serializzare e deserializzare al posto tuo, e di recente ho letto che hanno tolto nelle ultime versioni, la dipendenza su json.net, che toglie la possibilità di utilizzare alcuni attributi di serializzazione, ma embedda dentro di se un serializzatore snello e sopratutto integrato che ti permette di avere questo:
public class Connessione
{
public async Task<Dati> GetAsync()
{
RestRequest request = new RestRequest("url servizio");
request.Method = Method.GET;
RestClient client = new RestClient();
var response = await client.ExecuteTaskAsync<Dati>(request);
Dati dati = response.Data;
return dati;
}
}
public class Dati
{
[DeserializeAs(Name = "nome")]
public string Nome { get; set; }
[DeserializeAs(Name = "stato")]
public string Stato { get; set; }
}
in pratica non devi fare te la serializzazione o deserializzazione a mano, ma la fa dirattamente restsharp per te, ma non sfruttando più la libreria json.net, non ti da più la possibilità di utilizzare gli attributi come JsonProperty, ma ne ha soltanto uno che è DeserializeAs che prende solo due proprietà tra cui Name, per potere cambiare nome come facevi tu, quindi nel tuo caso è più che sufficiente e potresti togliere la dipendenza a json.net dal tuo progetto, a meno che proprio non ti serva per particolari cose o perchè ti piace e basta :) e puoi comunque utilizzarlo sostituendo il default*serializer* di restsharp come spiegato nel readme:
*** IMPORTANT CHANGE IN RESTSHARP VERSION 103 ***
In 103.0, JSON.NET was removed as a dependency.
If this is still installed in your project and no other libraries depend on
it you may remove it from your installed packages.
There is one breaking change: the default Json*Serializer* is no longer
compatible with Json.NET. To use Json.NET for serialization, copy the code
from https://github.com/restsharp/RestSharp/blob/86b31f9adf049d7fb821de8279154f41a17b36f7/RestSharp/Serializers/JsonSerializer.cs
and register it with your client:
var client = new RestClient();
client.JsonSerializer = new YourCustomSerializer();
The default Json*Deserializer* is mostly compatible, but it does not support
all features which Json.NET has (like the ability to support a custom [JsonConverter]
by decorating a certain property with an attribute). If you need these features, you
must take care of the deserialization yourself to get it working.
If you run into any compatibility issues with deserialization,
please report it to http://groups.google.com/group/restsharp
Spero di averti dato tutti gli elementi per proseguire bene con il tuo lavoro, fammi sapere se hai altri dubbi.
ciao,
Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic