Little background, my main experience has been vb.net/winforms and I've recently moved to c# and winui3 (desktop) and been banging my head to understand things. I've been going through a book called 'Learn WinUI 3.0' which has helped but isn't the greatest in explaining things.
Ok so I'm doing a project that I need to create a class and then spin it off into it's own thread. That thread then just runs in background doing things and updating properties on the main thread, which then updates the xaml gui and such. I've been having a real hard time trying to figure this out, and with winui3 desktop seemingly having some slightly different implementations of the way vb.net/uwp/wpf does it, googling has been a mess for me.
So I boiled it down to a real simple little test app here just to try and figure it out.
(I've edited the code from original to try something else, updated below)
I have a class called 'ChangeTextFromThread':
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ThreadTest {
public class ChangeTextFromThread {
private bool exitthread = false;
MainViewModel vm;
public ChangeTextFromThread(MainViewModel mainViewModel) {
vm = mainViewModel;
}
public void Start() {
ChangeText();
}
private String tempstring = "";
private int addup = 0;
private void ChangeText() {
do {
addup++;
vm.OutputString = addup.ToString();
Thread.Sleep(1);
}while (!exitthread) ;
}
}
}
And on my MainViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ThreadTest {
public class MainViewModel : BindableBase {
private String outputString = "Empty";
private String inputString = "";
private ChangeTextFromThread changeTextClass;
public String OutputString {
get { return outputString; }
set { SetProperty(ref outputString, value); }
}
public String InputString {
get { return inputString; }
set { SetProperty(ref inputString, value); }
}
public void Test() {
changeTextClass = new ChangeTextFromThread(this);
Thread changeTextThread = new Thread(changeTextClass.Start);
changeTextThread.Start();
}
}
}
And my BindableBase:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace ThreadTest {
public class BindableBase : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T originalValue, T newValue, [CallerMemberName] string propertyName = null) {
if (Equals(originalValue, newValue)) {
return false;
}
originalValue = newValue;
OnPropertyChanged(propertyName);
return true;
}
}
}
So user presses start, which spins up a new class on a new thread and starts it. The class is supposed to just count up and update the property of 'OutputString' (which is bound to a TextBlock in XAML). I read to reference the MainViewModel to the new thread class, which I did up above and I can see the properties on the MainViewModel from the new class. But when i run it, and press the button I get this error when it tries to update the property:
System.Runtime.InteropServices.COMException: 'The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))'
How do I change properties from a different thread?
Thank you if anyone can help, my brain is fried with a bad mix of old (winforms/vb) and new (winui/c#) knowledge.
What I have tried:
Various things I've googled. I know the answer is probably simple but my brain wont get over this wall.