UWP Error (RPC_E_WRONG_THREAD)

1

This error probably has been seen so many times and was avoided with some changes in code to run the specific code on UI Thread rather than worker thread. But in my situation the things are different.

Problem:

In my app, I was not able to implement Incremental Loading because I tried but it would fail every time and I didn't get any results. So I decided to do something same with GridView scroll, so I got the ScrollView inside the GridView and then I bind it with ViewChnaged and when the scroll reaches the end I call my function to load more items from the internet.

Everything works fine most of the time but then it gives the following exception.

The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

I know this Exception is caused when the UI Element is updated from Non-UI thread (or maybe something else that I don't know yet) but in the past I was able to avoid this with specifically calling the code from UI thread. Right now doing this is also not working, because it doesn't matter if I call the code from UI thread or worker thread it works and sometimes it gives out the Exception.

Here is the StackTrace that I got and the Source of the Exception is "Windows" but I don't know anything about it and how it can help me here:

   at Windows.UI.Xaml.Controls.TextBlock..ctor()
   at   WatchfreeWebsite.MoviesPage.<>c__DisplayClass27_0.<<LoadHtmlDocument>b__0>d.MoveNext()
   --- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at WatchfreeWebsite.MoviesPage.<GridViewScroll_ViewChanged>d__21.MoveNext()

I have 2 pages in my app that use the ScrollViewChanged event to load data. Now I was able to regenerate the problem by changing the pages one after another and going to the end of the view so that it loads more items.

With that keeping in mind I think that problem lies somewhere between the threads when one thread is working and it has not completed yet and the app calls the same thread to do something else or something else is going on that I don't know yet and need to dig a little deeper.

But in any case I thought it's worth getting a 2nd opinion to see how I can avoid this issue.

My Page 1: (MoviesPage) (where I got the exception now)

public MoviesPage()
    {
        InitializeComponent();
        NavigationCacheMode = NavigationCacheMode.Enabled;
        LoadHtmlDocument();
        MoviesList = new ObservableCollection<ItemsClass>();
        this.Loaded += MoviesPage_Loaded;
    }

    private void MoviesPage_Loaded(object sender, RoutedEventArgs e)
    {
        sv = ViewHelper.FindVisualTreeObject(dataGrid).OfType<ScrollViewer>().First();
        sv.ViewChanged += GridViewScroll_ViewChanged;
    }
private async void GridViewScroll_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
    {
        var currentScroll = sv.VerticalOffset;
        var maxScroll = sv.ScrollableHeight;
        if (currentScroll == maxScroll)
        {
            var pBar = new ProgressBar();
            pBar.IsIndeterminate = true;
            dataGrid.Footer = pBar;
            // end reached
            try
            {
                await LoadHtmlDocument();
            }
            catch (Exception ex)
            {
                ErrorDialog("Something happened while loading data\nThe Error is: " + ex.HResult + "\nMessage: " + ex.Message);
            }
        }
    }
public Task LoadHtmlDocument()
    {
        try
        {
            string url = "";
            return Task.Run(async () =>
            {
                if (firstRun) // first page
                {
                    url = MoviesBaseLink;
                    currentPageLink = MoviesBaseLink;
                    await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                    () =>
                    {
//#pragma warning disable
                        lv.ShowAsync();
//#pragma warning restore
                    });
                }
                else
                {
                    url = await GetNextPageLink();
                    currentPageLink = url;
                    if (url == "" || url == null)
                    {
                        TextBlock a = new TextBlock();
                        a.Text = "No more items found.";
                        dataGrid.Footer = a.HorizontalAlignment = HorizontalAlignment.Center; 
                        lv.Hide();
                        return;
                    }
                }

                var doc = new HtmlDocument();
                if (NetworkAvailable())
                {
                    doc = await new HtmlWeb().LoadFromWebAsync(url);
                }
                else
                {
                    doc = null;
                    lv.Hide();
                    return;
                }
                if (doc != null)
                {
                    Links(doc);
                }
            });

        }
        catch (Exception ex)
        {
            ErrorDialog("MoviesDoc_Download_Failed" + ex.Message);
            return null;
        }
    }

    private void Links(HtmlDocument doc)
    {
        try
        {
            listItems = 0;
            foreach (var link in doc.DocumentNode.Descendants("a").Where(pl => pl.Attributes.Contains("href")))
            {
                string dataValue = link.GetAttributeValue("href", "");
                if (dataValue.StartsWith("/watch") && dataValue.EndsWith(".html"))
                {
                    MoviesPageLinks[numberOfLinks] = MoviesBaseLink + dataValue.Trim();
                    listItems++;
                    numberOfLinks++;
                }
                if (numberOfLinks > 9999)
                {
                    break;
                }
            }
            ImageLinks(doc);
        }
        catch (Exception ex)
        {
            ErrorDialog("There was a problem while acquiring search links.\n" + ex.Message);
        }
    }

    private void ImageLinks(HtmlDocument doc)
    {
        try
        {
            foreach (var link in doc.DocumentNode.Descendants("img").Where(d => d.Attributes.Contains("src")))
            {
                if (link != null)
                {
                    if (link.Attributes["src"].Value == "/images/noposter.jpg")
                    {
                        MoviesImageLinks[numberOfImages] = @"ms-appx:///Assets/noposter.jpg";
                    }
                    else
                    {
                        MoviesImageLinks[numberOfImages] = string.Format("http:{0}", link.Attributes["src"].Value);
                    }
                    numberOfImages++;
                }
                if (numberOfImages == numberOfLinks)
                {
                    break;
                }
            }
            Titles(doc);
        }
        catch (Exception ex)
        {
            ErrorDialog("There was a problem in Image links.\n" + ex.Message);
        }
    }

    private async void Titles(HtmlDocument doc)
    {
        try
        {
            foreach (var link in doc.DocumentNode.Descendants("a").Where(t => t.Attributes.Contains("title")))
            {
                if (link != null && link.InnerText != "WatchFree.to" && link.InnerText != "Movies" && link.InnerText != "TV Shows")
                {
                    string x = link.GetAttributeValue("title", null);
                    x = x.Replace("Watch Putlocker", "");
                    x = x.Trim();
                    x = new Regex(@"(\(\d{4}\))(?:\s*\1)+").Replace(x, "$1").Trim();
                    MoviesTitles[numberOfTitles] = x;
                    numberOfTitles++;
                    if (numberOfTitles == numberOfLinks)
                    {
                        break;
                    }
                }
            }
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            () =>
            {
                MoviesList = ItemManager.GetMovieCollection(lastListItems, numberOfLinks, type);
                this.Bindings.Update();
                dataGrid.Footer = null;
                TextBlock b = new TextBlock();
                b.HorizontalAlignment = HorizontalAlignment.Center;
                dataGrid.Header = b.Text = "Recent Movies";
                lv.Hide();

            });
            lastListItems = numberOfLinks;
            firstRun = false;
        }
        catch (Exception ex)
        {
            ErrorDialog("There was a problem while acquiring movie titles.\n" + ex.Message);
        }
    }
private async Task<string> GetNextPageLink()
    {
        string lastLink = "";
        string nextPageLink = "";
        var doc = await new HtmlWeb().LoadFromWebAsync(currentPageLink);
        foreach (var link in doc.DocumentNode.Descendants("a").Where(t => t.Attributes.Contains("href")))
        {
            string value = link.GetAttributeValue("href", "");
            if (value.Contains("/?page=" + nextPage))
            {
                nextPageLink = value;
                lastLink = value;
                break;
            }
        }
        //--------------------------------------
        if (nextPageLink != "" && nextPageLink == lastLink)
        {
            nextPageLink = MoviesBaseLink + lastLink;
            nextPage++;
        }

        return nextPageLink;
    }

My Page 2: (TV Shows Page)

public TVShowsPage()
    {
        InitializeComponent();
        NavigationCacheMode = NavigationCacheMode.Enabled;
        this.Loaded += TVShowsPage_Loaded;
        LoadHtmlDocument();
        TVShowsList = new ObservableCollection<ItemsClass>();
    }

    private void TVShowsPage_Loaded(object sender, RoutedEventArgs e)
    {
        sv = ViewHelper.FindVisualTreeObject(dataGrid).OfType<ScrollViewer>().First();
        sv.ViewChanged += TVGridScroll_ViewChanged;
    }

    private async void TVGridScroll_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
    {
        var currentScroll = sv.VerticalOffset;
        var maxScroll = sv.ScrollableHeight;
        if (currentScroll == maxScroll)
        {
            var pBar = new ProgressBar();
            pBar.IsIndeterminate = true;
            dataGrid.Footer = pBar;
            // end reached
            try
            {
                await LoadHtmlDocument();
            }
            catch (Exception ex)
            {
                ErrorDialog("Something happened while loading data\nThe Error is: " + ex.HResult + "\nMessage: " + ex.Message);
            }
        }
    }
private Task LoadHtmlDocument()
    {
        try
        {
            string url = "";
            return Task.Run(async () =>
            {
                if (firstRun)
                {
                    url = TVShowsBaseLink;
                    currentPageLink = TVShowsBaseLink;
                    await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                    () =>
                    {
//#pragma warning disable
                        lv.ShowAsync();
//#pragma warning restore
                    });
                }
                else
                {
                    url = await GetNextPageLink();
                    currentPageLink = url;
                    if (url == "" || url == null)
                    {
                        dataGrid.Footer = new TextBlock().Text = "No more items found.";
                        lv.Hide();
                        return;
                    }
                }
                var doc = new HtmlDocument();
                if (NetworkAvailable())
                {
                    doc = await new HtmlWeb().LoadFromWebAsync(url);
                }
                else
                {
                    doc = null;
                    lv.Hide();
                    return;
                }
                if (doc != null)
                {
                    Links(doc);
                }
            });
        }
        catch (Exception ex)
        {
            ErrorDialog("Error_Downloading_WebPage\n" + ex.Message);
            return null;
        }
    }

    private async void Titles(HtmlDocument doc)
    {
        try
        {
            foreach (var link in doc.DocumentNode.Descendants("a").Where(t => t.Attributes.Contains("title")))
            {
                if (link != null && link.InnerText != "WatchFree.to" && link.InnerText != "Movies" && link.InnerText != "TV Shows")
                {
                    string x = link.GetAttributeValue("title", null);
                    x = x.Replace("Watch Putlocker", "");
                    x = x.Trim();
                    x = new Regex(@"(\(\d{4}\))(?:\s*\1)+").Replace(x, "$1").Trim();
                    TVShowsTitles[numberOfTitles] = x;
                    numberOfTitles++;
                    if (numberOfTitles == numberOfLinks)
                    {
                        break;
                    }
                }
            }
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            () =>
            {
                TVShowsList = ItemManager.GetTVShowsCollection(lastListItems, numberOfLinks, type);
                Bindings.Update();
                lv.Hide();
                TextBlock a = new TextBlock();
                a.HorizontalAlignment = HorizontalAlignment.Center;
                dataGrid.Header = a.Text = "TV Shows";
            });
            lastListItems = numberOfLinks;
            firstRun = false;
        }
        catch (Exception ex)
        {
            ErrorDialog("There was a problem while acquiring movie titles.\n" + ex.Message);
        }
    }

    private void ImageLinks(HtmlDocument doc)
    {
        try
        {
            foreach (var link in doc.DocumentNode.Descendants("img").Where(d => d.Attributes.Contains("src")))
            {
                if (link != null)
                {
                    if (link.Attributes["src"].Value == "/images/noposter.jpg")
                    {
                        TVShowsImageLinks[numberOfImages] = @"ms-appx:///Assets/noposter.jpg";
                    }
                    else
                    {
                        TVShowsImageLinks[numberOfImages] = string.Format("http:{0}", link.Attributes["src"].Value);
                    }
                    numberOfImages++;
                }
                if (numberOfImages == numberOfLinks)
                {
                    break;
                }
            }
            Titles(doc);
        }
        catch (Exception ex)
        {
            ErrorDialog("There was a problem in Image links.\n" + ex.Message);
        }
    }

    private void Links(HtmlDocument doc)
    {
        try
        {
            listItems = 0;
            foreach (var link in doc.DocumentNode.Descendants("a").Where(pl => pl.Attributes.Contains("href")))
            {
                string dataValue = link.GetAttributeValue("href", "");
                if (dataValue.StartsWith("/watch") && dataValue.EndsWith(".html"))
                {
                    TVShowsPageLinks[numberOfLinks] = MoviesPage.MoviesBaseLink + dataValue.Trim();
                    numberOfLinks++;
                    listItems++;
                }
                if (numberOfLinks > 9999)
                {
                    break;
                }
            }
            ImageLinks(doc);
        }
        catch (Exception ex)
        {
            ErrorDialog("There was a problem while acquiring search links.\n" + ex.Message);
        }
    }
 private async Task<string> GetNextPageLink()
    {
        string lastLink = "";
        string nextPageLink = "";
        var doc = await new HtmlWeb().LoadFromWebAsync(currentPageLink);
        foreach (var link in doc.DocumentNode.Descendants("a").Where(t => t.Attributes.Contains("href")))
        {
            string value = link.GetAttributeValue("href", "");
            if (value.Contains(@"=&page=" + nextPage))
            {
                lastLink = value;
                nextPageLink = value;
                break;
            }
        }
        //--------------------------------------
        if (nextPageLink != "" && nextPageLink == lastLink)
        {
            nextPageLink = MoviesPage.MoviesBaseLink + lastLink;
            nextPage++;
        }
        return nextPageLink;
    }

Note: Please note that this is only the relevant code that is displayed here, the pages include more code but that is only related to click-events.

Maybe I need to check, before loading more items, that the thread I am about to call again is finished working. Or maybe I need to call them from different threads but that wont be a good solution. So if someone can even point me in the right direction that would be really helpful. Thank you.

c#
multithreading
uwp
asked on Stack Overflow Dec 26, 2016 by Ahmar • edited Dec 26, 2016 by Uwe Keim

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0