2010-10-26 5 views
8

Fondamentalmente, sto ricevendo alcuni dati da un WebService e nel ResponseCallback sto cercando di riempire una ObservableCollection con i risultati ottenuti dalla risposta, ma ottengo un UnauthorizedAccessException "Accesso cross-thread non valido" quando provo a farlo.Problema di accesso a thread incrociati in ResponseCallback in Windows Phone 7

Quale sarebbe il modo migliore per compilare la raccolta osservabile quando ottengo il risultato?

Grazie!

Questo è il codice:

public ObservableCollection<Person> People { get; set; } 

    private void ResponseCallback(IAsyncResult asyncResult) 
    { 
     HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState; 
     HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult); 

     string responseString = string.Empty; 

     using (Stream content = response.GetResponseStream()) 
     { 
      if (request != null && response != null) 
      { 
       if (response.StatusCode == HttpStatusCode.OK) 
       { 
        XDocument document = XDocument.Load(content); 

        var people = from p in document.Descendants() 
          where p.Name.LocalName == "PersonInfo" 
          select Person.GetPersonFromXElement(p); 

        foreach (Person person in people) 
        { 
         this.People.Add(person); // this line throws the exception 
        } 
       } 
      } 

      content.Close(); 
     } 
    } 

risposta

2
+0

Grazie per il suggerimento, ma non sono molto sicuro di inserire questa soluzione nel codice di produzione. – Carlo

+0

Anche apparentemente la soluzione non funziona in Windows Phone 7. Non ho detto che questo era quello che stavo usando in un primo momento, ma ora l'ho aggiunto al titolo/tag. Grazie. – Carlo

+0

getcha. Non ho esperienza con il telefono 7 .. quindi buona fortuna! – climbage

1

Se si desidera aggiornare l'interfaccia utente (anche indirettamente, attraverso una raccolta osservato) da un altro thread basta è necessario utilizzare il dispatcher come segue:

Dispatcher.BeginInvoke(() => { //your ui update code }); 
+0

Sì, il fatto è che il codice che ho postato è nel mio modello di visualizzazione e non voglio che il mio modello di visualizzazione venga ereditato da DependencyObject solo per quello. Stiamo cercando di mantenere la memoria bassa e DependencyObject sono molto costosi. – Carlo

14

Ho esattamente lo stesso problema su WP7. Può essere risolto con il codice suggerito da Mick N e senza bisogno di ereditare da DO. Basta prendere un Dispatcher dalla classe di distribuzione statica.

Deployment.Current.Dispatcher.BeginInvoke(() => { //your ui update code });

Ma questo mi sembra strano tipo di soluzione, non ho mai hanno a che fare questo in Silverlight desktop.

Questo WP7 è specifico o esiste una soluzione migliore? Grazie.

+0

È specifico per WP7. Quello che ho fatto è che sto inviando il dispatcher di UserControl che ha chiamato il metodo ViewModel.Load(). Sembra: App.MainViewModel.Load (this.Dispatcher); e dentro uso il dispatcher per eseguire l'operazione asincrona, non sono sicuro che sia il modo migliore, ma funziona. – Carlo

+0

Bene, con l'approccio sopra, non è necessario passare nulla. C'è sempre un Dispatcher che ti aspetta in quella classe di Deployment. In ogni caso, questo significa che dal momento che le nostre app sono basate su Internet, il nostro codice sarà pieno di Dispatcher, ho ragione? – jumbo

+0

Ok, con i download di WebClient funziona tutto ok (binding ObservableCollection viene riempito senza bisogno di Dispatcher), ma quando uso RestSharp lib (per WP7), devo riempire ObsColl tramite Dispatcher. – jumbo