UWP: Updating UI through data binding from a background thread

巧了我就是萌 提交于 2019-11-26 23:40:30

问题


I'm using x:Bind (compiled binding) in my UWP app to bind a TextBlock to an integer property in the ViewModel which is converted to a string by a value converter. I am using a method in the ViewModel on the worker thread to set the properties and call the PropertyChanged event. However, I am getting an exception (specifically, it's in the XamlBindingSetters class in the MainPage.g.cs file) saying, "The application called an interface that was marshalled for a different thread." According to this post, this should work just fine in WPF; has this ease of functionality been removed in WinRT/UWP or am I doing something wrong?

Here's exactly what I'm doing.

My property is defined like this:

private int myProperty;

    public int MyProperty
    {
        get { return myProperty; }
        set
        {
            Set(ref myProperty, value);
        }
    }

The Set method is part of the Template 10 library and is defined:

public bool Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null) 
     { 
         if (object.Equals(storage, value)) 
             return false; 
         storage = value; 
         RaisePropertyChanged(propertyName); 
         return true; 
     } 

Nothing wrong there from what I can see; it just makes sure the new value is different than the old value and then calls RaisePropertyChanged(propertyName) which makes sure the app is actually running (not in design mode) and then raises the PropertyChanged event.

I set my property from a worker thread:

MyProperty = newValue;

and when it gets to the XamlBindingSetters class:

internal class XamlBindingSetters
    {
        public static void Set_Windows_UI_Xaml_Controls_TextBlock_Text(global::Windows.UI.Xaml.Controls.TextBlock obj, global::System.String value, string targetNullValue)
        {
            if (value == null && targetNullValue != null)
            {
                value = targetNullValue;
            }
            obj.Text = value ?? global::System.String.Empty;
        }
    };

it breaks on that last line (obj.Text = ...) and tells me that the application called an interface that was marshalled for a different thread. What am I doing wrong?


回答1:


You need to execute all graphical objects in the UI Thread.

  • First solution, using MVVM Light framework.

    see Simple example of DispatcherHelper

  • Second solution, using ISynchronizeInvoke.

Typical usage:

obj.Invoke((MethodInvoker) SomeMethod);

See How to Use ISynchronizeInvoke interface?



来源:https://stackoverflow.com/questions/32671719/uwp-updating-ui-through-data-binding-from-a-background-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!