Mishael Ogochukwu
Mishael Ogochukwu

Reputation: 129

Still getting the exception "application called an interface that was marshalled for a different thread" after using Dispatcher

public ObservableCollection<College> Colleges { get; set; }

My collection holding College data.

    public static Task<College> getCollege(string uniqueid)
    {
        return Task.Run(() =>

            Colleges.Where(coll => coll.UniqueID.Equals(uniqueid)).First()
        );
    }

Implementation for retrieving individual colleges.

GUI

    protected override async void OnNavigatedTo(NavigationEventArgs e)
    {
        var college = await DataSource.getCollege((string)e.Parameter);
        coll_grid.DataContext = college;
    }

This was my original implementation and it worked fine, but then I read Task.Run Etiquette by Stephen Cleary and from the gist of it you shouldn't use Task.Run in the implementation.

So I changed my codes this

    public static College getCollege(string uniqueid)
    {
        var match = CollegeData.Colleges.Where(coll => coll.UniqueID.Equals(uniqueid));
        return match.First();
    }

GUI

    protected override async void OnNavigatedTo(NavigationEventArgs e)
    {
        var college = await Task.Run(() => DataSource.getCollege((string)e.Parameter));
        coll_grid.DataContext = college;
    }

I got the "application called an interface that was marshalled for a different thread" exception

Then I added CoreApplication.MainView.Dispatcher.RunAsync to the GUI code to fix this.

GUI

    protected override async void OnNavigatedTo(NavigationEventArgs e)
    {
       await CoreApplication.MainView.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
        {
            var college = await Task.Run(() => DataSource.getCollege((string)e.Parameter);
            coll_grid.DataContext = college;
        });
    }

But I am still getting the same exception error. What may be the problem?

Upvotes: 0

Views: 188

Answers (1)

Igor Kulman
Igor Kulman

Reputation: 16361

First, there is absolutely no reason for you to use Task.Run when doing simple things as finding an element in a list/collection. Just use

 coll_grid.DataContext = Colleges.First(coll => coll.UniqueID.Equals(uniqueid))

But the reason the Dispatcher did not help you is that you need to do just the DataContext assignment on it.

var college = await Task.Run(() => DataSource.getCollege((string)e.Parameter);
await CoreApplication.MainView.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
    {
    coll_grid.DataContext = college;
 });

Because the call to await Task.Run(() => switches the thread.

Upvotes: 2

Related Questions