2010-09-21 2 views
1

J'ai ce morceau de code dans mon projet Silverlight:UnauthorizedAccessException pour un "MessageBox" dans SilverLight

private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    string baseUri = "http://foo.bar"; 
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(baseUri)); 
    request.BeginGetResponse(new AsyncCallback(ReadCallback),request); 
} 
private void ReadCallback(IAsyncResult asynchronousResult) 
{ 
    HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState; 
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult); 
    using (StreamReader streamReader1 = new StreamReader(response.GetResponseStream())) 
    { 
     string resultString = streamReader1.ReadToEnd(); 
     MessageBox.Show(resultString); 
    } 
} 

Quand je lance le code, je reçois l'exception suivante:

unauthorizedaccessexception 
Invalid cross-thread access. 

Je pensais que C'était un problème avec la chaîne retournée. Mais, même si je le mets:

MessageBox.Show("foobar"); 

la même exception augmente. Je pense que le problème vient de la fonction ReadCallback qui ne peut pas effectuer de telles actions.

Pouvez-vous m'aider?

Merci,

Cordialement

Répondre

4

Je pense que c'est parce que certaines parties de Silverlight ne peuvent être invoquées par le code et doivent provenir au lieu de l'entrée de l'utilisateur; Je pense que le MessageBox tombe dans cette catégorie. Donc, sauf si le MessageBox est appelé à la suite de l'utilisateur en appuyant sur un bouton ou un lien hypertexte, cela ne va pas fonctionner. Notez qu'il n'est pas nécessaire d'être dans le gestionnaire pour le bouton ou l'événement click de lien hypertexte; partout en bas de la hiérarchie des appels fonctionne. Ce que j'ai fait quand j'ai dû initier de telles actions à la suite d'un appel de service asynchrone, par exemple, c'est que j'ai dévoilé une ChildWindow contenant un hyperlien disant 'cliquez ici pour ouvrir votre x' ou tout ce que l'utilisateur essayait de faire pense que je l'ai utilisé pour ouvrir un fichier PDF généré par le serveur ou un fichier similaire). En outre, si le MessageBox peut en effet être appelé sans tout ce que je viens d'écrire, l'exception d'accès Cross-thread peut être résolue avec un appel à Dispatcher.Invoke ou Dispatcher.BeginInvoke en passant un délégué qui fait l'action réelle . C'est parce que les actions asynchrones (évidemment) ont lieu dans un thread séparé, mais Silverlight, comme WPF et comme WinForms avant eux, doit accéder à ses contrôles à partir d'un seul thread; invoquer en utilisant le Dispatcher du contrôle délègue les actions au bon thread.

Pour utiliser la solution BeginInvoke, essayez ceci au lieu d'appeler simplement MessageBox.Show:

string resultString = streamReader1.ReadToEnd(); 
Dispatcher.Invoke(new Action(() => MessageBox.Show(""))); 

C'est en supposant le code est un code-behind de contrôle (UserControl, Fenêtre, tout), de sorte que la propriété Dispatcher est disponible. Vous pouvez utiliser BeginInvoke au lieu de Invoke si vous souhaitez autoriser l'interface utilisateur à se mettre à jour correctement, mais la différence est généralement imperceptible.

+0

@Alex Paven: Je pense que vous avez manqué la vraie question. Le MessageBox était le rouge-hareng, il a ajouté au problème de cross-thread après. –

+0

Oui, également mis à jour ma réponse immédiatement pour inclure Dispatcher.Invoke, mais je comprends parfaitement que j'ai un style alambiqué et prolixe qui peut déclencher des réactions TLDR. –

+1

+1 pour le dernier paragraphe, 'Dispatcher.BeginInvoke' est ce qui est nécessaire. – AnthonyWJones