Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
362 views
in Technique[技术] by (71.8m points)

c# - UWP: Updating UI through data binding from a background thread

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

Typical usage:

obj.Invoke((MethodInvoker) SomeMethod);

See How to Use ISynchronizeInvoke interface?

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...