【问题标题】:unauthorizedaccessexception for a "MessageBox" in SilverLightSilverLight 中“MessageBox”的未授权访问异常
【发布时间】:2010-09-22 01:59:13
【问题描述】:

我的 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 函数。

你能帮帮我吗?

谢谢,

问候

【问题讨论】:

    标签: silverlight exception unauthorized


    【解决方案1】:

    我认为这是因为 Silverlight 的某些部分不能由代码调用,而必须源自用户输入;我认为 MessageBox 属于这一类。因此,除非由于用户按下按钮或超链接而调用 MessageBox,否则它不会起作用。

    请注意,它不必在按钮或超链接单击事件的处理程序中;调用层次结构进一步向下的任何地方都有效。例如,当由于异步服务调用而需要启动此类操作时,我基本上所做的是显示一个 ChildWindow,其中包含一个超链接,上面写着“单击此处打开您的 x”或用户尝试执行的任何操作(我我想我用它来打开服务器生成的 PDF 或类似文件)。

    另外,如果 MessageBox 确实可以在没有我刚才写的所有错误的情况下被调用,则可以通过调用 Dispatcher.Invoke 或 Dispatcher.BeginInvoke 并传递一个执行实际操作的委托来解决跨线程访问异常。这是因为异步操作(显然)发生在单独的线程中,但 Silverlight 与 WPF 和之前的 WinForms 一样,只需要从一个线程访问其控件;使用控件的 Dispatcher 调用会将操作委托给正确的线程。

    要使用 BeginInvoke 解决方案,试试这个而不是简单地调用 MessageBox.Show:

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

    假设代码位于 Control 代码隐藏(UserControl、Window 等)中,因此 Dispatcher 属性可用。如果您想让用户界面有时间正确更新自身,您可以使用 BeginInvoke 而不是 Invoke,但通常差异是难以察觉的。

    【讨论】:

    • @Alex Paven:我认为您错过了实际问题。 MessageBox 是他后来添加到跨线程问题的红鲱鱼。
    • 是的,我也立即更新了我的答案以包括 Dispatcher.Invoke,但我完全理解我的风格复杂而冗长,可能会引发 TLDR 反应。
    • +1 最后一段 Dispatcher.BeginInvoke 是需要的。
    • 感谢您的回答。您能否告诉我如何使用 Dispatcher.BeginInvoke 功能处理此异常?
    • 编辑了答案以包含 (Begin)Invoke 的示例。忘了提到 Invoke 和 BeginInvoke 都允许指定请求的优先级,但您也可以在 MSDN 上找到它。它们还允许将参数传递给代表。编辑:还更正了语法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    相关资源
    最近更新 更多