【问题标题】:UnauthorizedAccessException: Invalid cross-thread access in Silverlight application (XAML/C#)UnauthorizedAccessException:Silverlight 应用程序中的无效跨线程访问 (XAML/C#)
【发布时间】:2010-08-06 00:58:26
【问题描述】:

对 C# 比较陌生,想尝试使用一些第三方 Web 服务 API。

这是 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>

这里是 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";
    }

我猜这是由于回调在与 UI 不同的线程上执行的事实引起的?在 C# 中处理这些类型的交互的正常流程是什么?

谢谢。

【问题讨论】:

  • 感谢大家的回复。
  • 另一种方法是使用 this.Dispatcher 但这个链接对你很有帮助。 humrahimcs.wordpress.com/wp-admin/…
  • 你为什么不接受史蒂夫威尔科克的回答?

标签: c# silverlight


【解决方案1】:

使用 CheckAccess 调用轻松实现跨线程访问的一种有用方法是将实用方法封装在静态类中 - 例如

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

然后您可以在后台线程上包装任何更新 UI 的调用,如下所示:

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

这样您不必知道您是否在后台线程上,并且避免了向每个控件添加方法来检查这一点的开销。

【讨论】:

    【解决方案2】:

    另一种方法是使用this.Dispatcher.CheckAccess() 函数。它与您在 WPF 中获得的相同,但它不会出现在您的智能感知中,因此您可能没有看到它。您要做的是检查您是否可以访问 UI 线程,如果没有,则在 UI 线程上递归调用自己

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

    这只是一个非常简单的示例,一旦您拥有多个控件,就会变得难以管理。对于一些 WPF/Silverlight 的东西,我使用了一个通用函数,它还需要更新 UI 控件以及更新本身,这样我就没有这些函数之一用于页面上可能需要更新的每个控件后台线程的结果。

    【讨论】:

      【解决方案3】:

      如您所料,silverlight 在单独的线程上异步执行所有 Web 请求以避免冻结 UI。

      要将消息发送到 UI 线程,您可以使用 Deployment.Current.Dispatcher.BeginInvoke(delegate, object[]) 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多