1

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);
    }
}

コードを実行すると、次の例外が発生します。

unauthorizedaccessexception
Invalid cross-thread access.

返された文字列に問題があると思いました。しかし、私がこれを置いたとしても:

MessageBox.Show("foobar");

同じ例外が発生します。問題は、そのようなアクションを実行できないReadCallback関数にあると思います。

手伝って頂けますか?

ありがとうございました、

よろしく

4

1 に答える 1

4

これは、Silverlightの特定の部分をコードで呼び出すことができず、代わりにユーザー入力から発信する必要があるためだと思います。MessageBoxはこのカテゴリに分類されると思います。したがって、ユーザーがボタンまたはハイパーリンクを押した結果としてMessageBoxが呼び出されない限り、メッセージボックスは機能しません。

ボタンまたはハイパーリンクのクリックイベントのハンドラーにある必要はないことに注意してください。呼び出し階層のさらに下のどこでも機能します。たとえば、非同期サービス呼び出しの結果としてこのようなアクションを開始する必要があるときに基本的に行ったことは、「ここをクリックしてxを開く」というハイパーリンクまたはユーザーが実行しようとしていることを含むChildWindowを表示したことです(Iサーバーで生成されたPDFまたは同様のファイルを開くために使用したと思います)。

また、私が今書いたすべての悪意なしにMessageBoxを実際に呼び出すことができる場合は、実際のアクションを実行するデリゲートを渡すDispatcher.InvokeまたはDispatcher.BeginInvokeを呼び出すことで、クロススレッドアクセス例外を解決できます。これは、非同期アクションが(明らかに)別のスレッドで実行されるためですが、Silverlightは、WPFやその前のWinFormsのように、1つのスレッドからのみコントロールにアクセスする必要があります。コントロールのディスパッチャーを使用して呼び出すと、アクションが正しいスレッドに委任されます。

BeginInvokeソリューションを使用するには、単にMessageBox.Showを呼び出すのではなく、これを試してください。

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

これは、コードが制御コードビハインド(UserControl、Windowなど)にあることを前提としているため、Dispatcherプロパティを使用できます。ユーザーインターフェイスがそれ自体を適切に更新できるようにする場合は、Invokeの代わりにBeginInvokeを使用できますが、通常、違いは認識できません。

于 2010-09-21T15:45:25.700 に答える