我创建了一些测试代码,以便尝试弄清楚如何在 UWP 中正确使用多个窗口。我想看看我是否可以触发一个事件并让多个窗口在事件处理程序中更新它们的 UI。我终于得到了一些工作,但我不完全确定它为什么工作。
这是在我的页面中创建的课程
public class NumberCruncher
{
private static Dictionary<int, Tuple<CoreDispatcher, NumberCruncher>> StaticDispatchers { get; set; }
static NumberCruncher()
{
StaticDispatchers = new Dictionary<int, Tuple<CoreDispatcher, NumberCruncher>>();
}
public NumberCruncher()
{
}
public event EventHandler<NumberEventArgs> NumberEvent;
public static void Register(int id, CoreDispatcher dispatcher, NumberCruncher numberCruncher)
{
StaticDispatchers.Add(id, new Tuple<CoreDispatcher, NumberCruncher>(dispatcher, numberCruncher));
}
public async Task SendInNumber(int id, int value)
{
foreach (var dispatcher in StaticDispatchers)
{
await dispatcher.Value.Item1.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Debug.WriteLine($"invoking {dispatcher.Key}");
dispatcher.Value.Item2.NumberEvent?.Invoke(null, new NumberEventArgs(id, value));
});
}
}
}
这是我的 MainPage 代码的相关部分
NumberCruncher numberCruncher;
public MainPage()
{
this.InitializeComponent();
numberCruncher = new NumberCruncher();
numberCruncher.NumberEvent += NumberCruncher_NumberEvent;
}
private async void NumberCruncher_NumberEvent(object sender, NumberEventArgs e)
{
listView.Items.Add($"{e.Id} sent {e.Number}");
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
NumberCruncher.Register(ApplicationView.GetForCurrentView().Id, Window.Current.Dispatcher, numberCruncher);
}
我有一个按钮可以创建 MainPage 的新视图。然后我有另一个调用该SendInNumber()
方法的按钮。
当我导航到 MainPage 时,我为窗口和 NumberCruncher 实例注册了 Dispatcher。然后在触发事件时,我使用 NumberCruncher EventHandler 来处理特定的 Dispatcher。
这可以在不引发封送处理异常的情况下工作。如果我尝试使用当前类的 EventHandler
await dispatcher.Value.Item1.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Debug.WriteLine($"invoking {dispatcher.Key}");
NumberEvent?.Invoke(null, new NumberEventArgs(id, value));
});
尝试将项目添加到 listView 时出现编组异常。但是,如果我在 MainPage 中维护 SynchronizationContext,然后使用 SynchronizationContext.Post 更新 listView。它工作正常
SynchronizationContext synchronizationContext;
public MainPage()
{
this.InitializeComponent();
numberCruncher = new NumberCruncher();
numberCruncher.NumberEvent += NumberCruncher_NumberEvent;
synchronizationContext = SynchronizationContext.Current;
}
private async void NumberCruncher_NumberEvent(object sender, NumberEventArgs e)
{
synchronizationContext.Post(_ =>
{
listView.Items.Add($"{e.Id} sent {e.Number}");
}, null);
}
但是,这不起作用并在尝试更新 listView 时引发封送处理异常。
private async void NumberCruncher_NumberEvent(object sender, NumberEventArgs e)
{
await CoreApplication.GetCurrentView().CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
listView.Items.Add($"{e.Id} sent {e.Number}");
});
}
这里发生了什么?