WinUI3中CoreDispatcher转DispatcherQueue适配AudioGraph事件处理
WinUI3中用DispatcherQueue替代CoreDispatcher处理AudioGraph事件的正确方式
问题根源
你遇到的Object reference not set to an instance of an object错误,是因为WinUI3的Window类不再提供Dispatcher属性(这是UWP时期的API),直接调用Dispatcher.RunAsync会导致空引用。WinUI3中统一使用DispatcherQueue来实现UI线程调度。
代码转换步骤
1. 替换CoreDispatcher为DispatcherQueue
将原来的事件处理方法,从依赖CoreDispatcher改为使用DispatcherQueue:
原来的错误代码:
private async void FileInputNodeOnFileCompleted(AudioFileInputNode sender, object args) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { sender.Stop(); sender.Reset(); }); }
修改后的正确代码:
private void FileInputNodeOnFileCompleted(AudioFileInputNode sender, object args) { // 使用Window的DispatcherQueue将操作调度到UI线程 _ = DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () => { sender.Stop(); sender.Reset(); // 同步更新UI状态,修复播放结束后按钮状态未重置的问题 playButton.Content = "Play Recorded File"; graph2.Stop(); }); }
关键差异说明
- WinUI3的
Window内置DispatcherQueue属性,直接通过this.DispatcherQueue即可获取,无需额外初始化 DispatcherQueue.TryEnqueue是同步方法,返回布尔值表示是否成功将任务加入队列,不需要用await- 新增了UI状态更新逻辑,原代码播放结束后按钮仍显示停止状态,这里一起修复
额外代码优化建议
你的测试代码中还有一处逻辑问题:在TogglePlay方法里,刚创建fileInputNode后就判断Position == TimeSpan.FromSeconds(0)并立即停止播放,这会导致刚点击播放就自动停止。建议删除这段逻辑:
// 删除以下代码块 if (fileInputNode.Position == TimeSpan.FromSeconds(0)) { graph2.Stop(); playButton.Content = "Play Recorded File"; }
完整修改后的核心代码片段
结合所有调整,最终的事件处理方法和播放逻辑如下:
private void FileInputNodeOnFileCompleted(AudioFileInputNode sender, object args) { _ = DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () => { sender.Stop(); sender.Reset(); playButton.Content = "Play Recorded File"; graph2.Stop(); }); } private async void TogglePlay() { //Toggle playback if (playButton.Content.Equals("Play Recorded File")) { if (fileInputNode != null) { fileInputNode.Dispose(); } CreateAudioFileInputNodeResult fileInputResult = await graph2.CreateFileInputNodeAsync(file); if (AudioFileNodeCreationStatus.Success != fileInputResult.Status) { // Cannot read input file return; } fileInputNode = fileInputResult.FileInputNode; fileInputNode.AddOutgoingConnection(deviceOutputNode2); fileInputNode.StartTime = TimeSpan.FromSeconds(0); graph2.Start(); playButton.Content = "Stop Playing Recorded File"; fileInputNode.FileCompleted += FileInputNodeOnFileCompleted; } else { graph2.Stop(); playButton.Content = "Play Recorded File"; } }
内容的提问来源于stack exchange,提问作者Giovanni Briones
相关产品推荐
相关产品推荐

