UnauthorizedAccessException: Invalid cross-thread access in Silverlight application (XAML/C#)

后端 未结 3 1970
情书的邮戳
情书的邮戳 2020-12-18 22:55

Relatively new to C# and wanted to try playing around with some third party web service API\'s with it.

Here is the XAML code

    

        
相关标签:
3条回答
  • 2020-12-18 23:40

    Another way to do this is to use the this.Dispatcher.CheckAccess() function. It is the same as what you get in WPF but it doesn't show up in your intellisense so you may not have seen it. What you do is check if you have access to the UI thread, and if you don't you recursively call yourself back on the UI thread.

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

    This is just a very simple example and can get unmanageable once you have more than a few controls. For some WPF/Silverlight stuff i have used a generic function which also takes the UI control to be updated as well as the update itself, that way i don't have one of these functions for every control on the page that may need updating from the results of a background thread.

    0 讨论(0)
  • 2020-12-18 23:42

    As you guessed, silverlight executes all web request asynchronously on a separated thread to avoid freezing the UI.

    To dispatch messages to the UI thread you can use the Deployment.Current.Dispatcher.BeginInvoke(delegate, object[]) method.

    0 讨论(0)
  • 2020-12-18 23:52

    A useful way to get easy cross thread access with the CheckAccess call is to wrap up a utility method in a static class - e.g.

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

    then you can wrap any calls that update the UI where you may be on a background thread like so:

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

    This way you don't have to know whether you are on a background thread or not and it avoids the overhead of adding methods to every control to check this.

    0 讨论(0)
提交回复
热议问题