2010-08-06 10 views
12

Relativamente nuevo para C# y quería intentar jugar con algunas API de servicios web de terceros con él.UnauthorizedAccessException: Acceso de hilos cruzados no válido en la aplicación Silverlight (XAML/C#)

Este es el código XAML

<Grid x:Name="ContentGrid" Grid.Row="1"> 
     <StackPanel> 
      <Button Content="Load Data" Click="Button_Click" /> 
      <TextBlock x:Name="TwitterPost" Text="Here I am"/> 
     </StackPanel> 
    </Grid> 

y aquí está el código C#

private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://api.twitter.com/1/users/show/keykoo.xml"); 
     request.Method = "GET"; 

     request.BeginGetResponse(new AsyncCallback(twitterCallback), request); 
    } 

    private void twitterCallback(IAsyncResult result) 
    { 
     HttpWebRequest request = (HttpWebRequest)result.AsyncState; 
     HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); 
     TextReader reader = new StreamReader(response.GetResponseStream()); 
     string strResponse = reader.ReadToEnd(); 

     Console.WriteLine("I am done here"); 
     TwitterPost.Text = "hello there"; 
    } 

supongo que esto es causado por el hecho de que la devolución de llamada se ejecuta en un hilo separado de la ¿UI? ¿Cuál es el flujo normal para tratar este tipo de interacciones en C#?

Gracias.

+0

Gracias a todos por sus respuestas. – PolandSpring

+0

Otra forma de hacerlo es utilizar el this.Dispatcher pero este enlace es muy útil para usted. http://humrahimcs.wordpress.com/wp-admin/post.php?post=420&action=edit&message=6&postpost=v2 – DoNetDeveloper

+0

¿Por qué no acepta la respuesta de Steve Willcock? –

Respuesta

2

Otra forma de hacerlo es utilizar la función this.Dispatcher.CheckAccess(). Es lo mismo que obtienes en WPF pero no aparece en tu intellisense por lo que es posible que no lo hayas visto. Lo que debe hacer es verificar si tiene acceso al hilo de la interfaz de usuario, y si no lo hace recíprocamente llame de nuevo en la interfaz de usuario hilo.

private void twitterCallback(IAsyncResult result) 
{ 
    HttpWebRequest request = (HttpWebRequest)result.AsyncState; 
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); 
    TextReader reader = new StreamReader(response.GetResponseStream()); 
    string strResponse = reader.ReadToEnd(); 

    Console.WriteLine("I am done here"); 
    ////TwitterPost.Text = "hello there"; 
    postMyMessage(TwitterPost.Text); 
} 

private void postMyMessage(string text) 
{ 
    if (this.Dispatcher.CheckAccess()) 
     TwitterPost.Text = text; 
    else 
     this.Dispatcher.BeginInvoke(new Action<string>(postMyMessage), text); 
} 

Esto es solo un ejemplo muy simple y puede volverse inmanejable una vez que tiene más de unos pocos controles. Para algunas cosas de WPF/Silverlight he usado una función genérica que también lleva el control de la interfaz de usuario para actualizarse, así como la actualización en sí, de esa manera no tengo una de estas funciones para cada control en la página que puede necesitar actualización desde los resultados de un hilo de fondo.

29

Una forma útil de obtener acceso directo a la secuencia cruzada con la llamada CheckAccess es resumir un método de utilidad en una clase estática, p.

public static class UIThread 
{ 
    private static readonly Dispatcher Dispatcher; 

    static UIThread() 
    { 
     // Store a reference to the current Dispatcher once per application 
     Dispatcher = Deployment.Current.Dispatcher; 
    } 

    /// <summary> 
    /// Invokes the given action on the UI thread - if the current thread is the UI thread this will just invoke the action directly on 
    /// the current thread so it can be safely called without the calling method being aware of which thread it is on. 
    /// </summary> 
    public static void Invoke(Action action) 
    { 
     if (Dispatcher.CheckAccess()) 
      action.Invoke(); 
     else 
      Dispatcher.BeginInvoke(action); 
    } 
} 

continuación, se puede envolver cualquier llamada que actualizan la interfaz de usuario, donde usted puede estar en un subproceso de fondo de este modo:

private void twitterCallback(IAsyncResult result) 
{ 
     HttpWebRequest request = (HttpWebRequest)result.AsyncState; 
     HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); 
     TextReader reader = new StreamReader(response.GetResponseStream()); 
     string strResponse = reader.ReadToEnd(); 

     UIThread.Invoke(() => TwitterPost.Text = "hello there"); 
} 

De esta manera usted no tiene que saber si usted está en un fondo hilo o no y evita la sobrecarga de agregar métodos a cada control para verificar esto.

+0

Esto funciona muy bien para Windows Phone 7. gran solución. – scottbates22

+0

¡Impresionante! Justo lo que necesitaba. –

Cuestiones relacionadas