尝试在 ViewModel 中更新 Ui 属性 时 DispatcherQueue 为 null
DispatcherQueue null when trying to update Ui property in ViewModel
在 WinUI 3 桌面应用程序中,我有一个 属性 要更新,它通过 x:Bind
.
绑定到 ui
我想像在 WPF 中一样使用 Dispatcher
进入 UI 线程并避免在更新 prop 时出现线程错误:
System.Runtime.InteropServices.COMException: 'The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))'
我只是不确定如何在 Win 中执行此操作UI 3,当我尝试时
DispatcherQueue.GetForCurrentThread().TryEnqueue(() =>
{
AeParty.OnSyncHub = false; // Prop bound in ui using x:Bind
});
我收到这个错误
DispatcherQueue.GetForCurrentThread()
为空
我也试过:
this.DispatcherQueue.TryEnqueue(() =>
{
AeParty.OnSyncHub = false;
});
但无法编译:
然后我发现 this GitHub 问题,所以我尝试了:
SynchronizationContext.Current.Post((o) =>
{
AeParty.OnSyncHub = false;
}, null);
这行得通,但为什么我不能在我的 VM 中使用 Dispatcher 进入 UI 线程?
DispatcherQueue.GetForCurrentThread()
在实际具有 DispatcherQueue
的线程上调用时仅 return 是 DispatcherQueue
。如果你在后台线程上调用它,确实没有 DispatcherQueue
被 returned.
所以诀窍是在 UI 线程上调用该方法并将 return 值存储在一个变量中,然后您可以从后台线程使用该变量,例如:
public sealed partial class MainWindow : YourBaseClass
{
public MainWindow()
{
this.InitializeComponent();
}
public ViewModel ViewModel { get; } = new ViewModel();
}
public class ViewModel : INotifyPropertyChanged
{
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
public ViewModel()
{
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
string val = i.ToString();
_dispatcherQueue.TryEnqueue(() =>
{
Text = val;
});
Thread.Sleep(2000);
}
});
}
private string _text;
public string Text
{
get { return _text; }
set { _text = value; NotifyPropertyChanged(nameof(Text)); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
在 WinUI 3 桌面应用程序中,我有一个 属性 要更新,它通过 x:Bind
.
我想像在 WPF 中一样使用 Dispatcher
进入 UI 线程并避免在更新 prop 时出现线程错误:
System.Runtime.InteropServices.COMException: 'The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))'
我只是不确定如何在 Win 中执行此操作UI 3,当我尝试时
DispatcherQueue.GetForCurrentThread().TryEnqueue(() =>
{
AeParty.OnSyncHub = false; // Prop bound in ui using x:Bind
});
我收到这个错误
DispatcherQueue.GetForCurrentThread()
为空
我也试过:
this.DispatcherQueue.TryEnqueue(() =>
{
AeParty.OnSyncHub = false;
});
但无法编译:
然后我发现 this GitHub 问题,所以我尝试了:
SynchronizationContext.Current.Post((o) =>
{
AeParty.OnSyncHub = false;
}, null);
这行得通,但为什么我不能在我的 VM 中使用 Dispatcher 进入 UI 线程?
DispatcherQueue.GetForCurrentThread()
在实际具有 DispatcherQueue
的线程上调用时仅 return 是 DispatcherQueue
。如果你在后台线程上调用它,确实没有 DispatcherQueue
被 returned.
所以诀窍是在 UI 线程上调用该方法并将 return 值存储在一个变量中,然后您可以从后台线程使用该变量,例如:
public sealed partial class MainWindow : YourBaseClass
{
public MainWindow()
{
this.InitializeComponent();
}
public ViewModel ViewModel { get; } = new ViewModel();
}
public class ViewModel : INotifyPropertyChanged
{
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
public ViewModel()
{
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
string val = i.ToString();
_dispatcherQueue.TryEnqueue(() =>
{
Text = val;
});
Thread.Sleep(2000);
}
});
}
private string _text;
public string Text
{
get { return _text; }
set { _text = value; NotifyPropertyChanged(nameof(Text)); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}