我在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函数。
你能帮助我吗?
谢谢,
此致
答案 0 :(得分:4)
我认为这是因为Silverlight的某些部分不能被代码调用,而必须来自用户输入;我认为MessageBox属于这一类。因此,除非由于用户按下按钮或超链接而调用MessageBox,否则它将不起作用。
请注意,它不必位于按钮或超链接点击事件的处理程序中;在调用层次结构的任何地方工作。例如,当我因为异步服务调用而需要启动此类操作时,我基本上做了什么,我将显示一个包含超级链接的ChildWindow,其中包含“点击此处打开您的x”或用户尝试执行的任何操作(I我认为我用它来打开服务器生成的PDF或类似文件。
此外,如果MessageBox确实可以在没有我刚写过的所有malarkey的情况下调用,则可以通过调用Dispatcher.Invoke或Dispatcher.BeginInvoke来传递执行实际操作的委托来解决跨线程访问异常。这是因为异步操作(显然)发生在一个单独的线程中,但Silverlight,比如WPF和WinForms之前的需要,只需要从一个线程访问它的控件;使用控件的Dispatcher调用将操作委托给正确的线程。
要使用BeginInvoke解决方案,请尝试此操作,而不是简单地调用MessageBox.Show:
string resultString = streamReader1.ReadToEnd();
Dispatcher.Invoke(new Action(() => MessageBox.Show("")));
假设代码位于Control代码隐藏(UserControl,Window,any)中,因此Dispatcher属性可用。如果要允许用户界面时间正确更新自己,可以使用BeginInvoke而不是Invoke,但通常差别是难以察觉的。