Как преобразовать CoreDispatcher в DispatcherQueue для обработчика событий AudioGraph

Поскольку CoreDispatcher устарел в WinUI 3 Windows App SDK и заменен DispatcherQueue, как можно преобразовать следующий код для правильного использования DispatcherQueue?

fileInputNode.FileCompleted += FileInputNodeOnFileCompleted;

private async void FileInputNodeOnFileCompleted(AudioFileInputNode sender, object args)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        sender.Stop();               
        sender.Reset();        
    });
}

Другая причина обновить код для использования DispatcherQueue заключается в том, что при использовании CoreDispatcher в коде возникает следующая ошибка:

В экземпляре объекта не задана ссылка на объект.

РЕДАКТИРОВАТЬ

По запросу YangXiaoPo-MSFT вот воспроизводимый образец тестового приложения, содержащего рассматриваемую проблему.

Ниже приведен относящийся к нему XAML:

<Window
x:Class = "Test_3_Take_2.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "using:Test_3_Take_2"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable = "d">

<StackPanel Orientation = "Vertical" HorizontalAlignment = "Center" VerticalAlignment = "Center">
    <Button x:Name = "recordStopButton" Content = "Record"   Click = "recordStopButton_Click"/>
    <Button x:Name = "playButton" Content = "Play Recorded File" Margin = "0,50,0,0" IsEnabled = "False" Click = "playButton_Click"/>
</StackPanel>
</Window>

И следующий код:

using Microsoft.UI.Xaml;
using System;
using System.Threading.Tasks;
using Windows.Media.Audio;
using Windows.Media.MediaProperties;
using Windows.Storage;
using Windows.Media.Transcoding;
using Windows.Media.Capture;
using Windows.Media.Render;
using Microsoft.UI.Dispatching;

namespace Test_3_Take_2
{


public sealed partial class MainWindow : Window
{

    private AudioGraph graph, graph2;
    private AudioFileInputNode fileInputNode;
    private AudioFileOutputNode fileOutputNode;
    private AudioDeviceOutputNode deviceOutputNode, deviceOutputNode2;
    private AudioDeviceInputNode deviceInputNode;
    private StorageFolder temporaryFolder = ApplicationData.Current.TemporaryFolder;
    private StorageFile file;
    public MainWindow()
    {
        this.InitializeComponent();

        this.Title = "Test 3 Take 2";

        var root = this.Content as FrameworkElement;
        if (root != null)
            root.Loaded += async (s, e) => await CreateAudioGraph();

        var root2 = this.Content as FrameworkElement;
        if (root2 != null)
            root2.Loaded += async (s, e) => await CreateAudioGraph2();
    }

    private void playButton_Click(object sender, RoutedEventArgs e)
    {

        if (file != null)
        {
           
                TogglePlay();
            
        }

    }

    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;

    if (fileInputNode.Position == TimeSpan.FromSeconds(0))
    {
        graph2.Stop();
        playButton.Content = "Play Recorded File";

    }
   


}
else
{
    graph2.Stop();
    playButton.Content = "Play Recorded File";

}
}


private async void FileInputNodeOnFileCompleted(AudioFileInputNode sender, object args) {
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        sender.Stop();               
        sender.Reset();        
    }); }

private async void recordStopButton_Click(object sender, RoutedEventArgs e)
{

    await ToggleRecordStop();

} 

private async Task ToggleRecordStop()
{
    
             

    if (recordStopButton.Content.Equals("Record"))
    {

        playButton.Content = "Play Recorded File";
        playButton.IsEnabled = false;
        
        if (deviceInputNode != null)
        {

            deviceInputNode.Dispose();

            CreateAudioDeviceInputNodeResult deviceInputNodeResult = await graph.CreateDeviceInputNodeAsync(MediaCategory.Other);
            if (deviceInputNodeResult.Status != AudioDeviceNodeCreationStatus.Success)
            {
                // Cannot create device input node
                return;
            }

            deviceInputNode = deviceInputNodeResult.DeviceInputNode;

        }
        
         file = await temporaryFolder.CreateFileAsync("file1.mp3",
CreationCollisionOption.ReplaceExisting);
        // File can be null if cancel is hit in the file picker
        if (file == null)
        {
            return;
        }

        MediaEncodingProfile fileProfile = MediaEncodingProfile.CreateMp3(AudioEncodingQuality.High);

        // Operate node at the graph format, but save file at the specified format
        CreateAudioFileOutputNodeResult fileOutputNodeResult = await graph.CreateFileOutputNodeAsync(file, fileProfile);

        if (fileOutputNodeResult.Status != AudioFileNodeCreationStatus.Success)
        {
            // FileOutputNode creation failed
            return;
        }

        fileOutputNode = fileOutputNodeResult.FileOutputNode;

        // Connect the input node to both output nodes
        deviceInputNode.AddOutgoingConnection(fileOutputNode);
        deviceInputNode.AddOutgoingConnection(deviceOutputNode);
        graph.Start();
        recordStopButton.Content = "Stop";
        
    }
    else if (recordStopButton.Content.Equals("Stop"))
    {
        // Good idea to stop the graph to avoid data loss
        graph.Stop();
        

        TranscodeFailureReason finalizeResult = await fileOutputNode.FinalizeAsync();
        if (finalizeResult != TranscodeFailureReason.None)
        {
            // Finalization of file failed. Check result code to see why
            return;
        }

        recordStopButton.Content = "Record";
        playButton.IsEnabled = true;
    }
}

private async Task CreateAudioGraph()
{
    AudioGraphSettings settings = new AudioGraphSettings(AudioRenderCategory.Media);
    settings.QuantumSizeSelectionMode = QuantumSizeSelectionMode.LowestLatency;

    CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings);

    if (result.Status != AudioGraphCreationStatus.Success)
    {
        // Cannot create graph
        return;
    }

    graph = result.Graph;

    // Create a device output node
    CreateAudioDeviceOutputNodeResult deviceOutputNodeResult = await graph.CreateDeviceOutputNodeAsync();
    if (deviceOutputNodeResult.Status != AudioDeviceNodeCreationStatus.Success)
    {
        // Cannot create device output node
       
        return;
    }

    deviceOutputNode = deviceOutputNodeResult.DeviceOutputNode;


    // Create a device input node using the default audio input device
    CreateAudioDeviceInputNodeResult deviceInputNodeResult = await graph.CreateDeviceInputNodeAsync(MediaCategory.Other);
    if (deviceInputNodeResult.Status != AudioDeviceNodeCreationStatus.Success)
    {
        // Cannot create device input node
        return;
    }

    deviceInputNode = deviceInputNodeResult.DeviceInputNode;

    
}

private async Task CreateAudioGraph2()
{
    // Create an AudioGraph with default settings
    AudioGraphSettings settings = new AudioGraphSettings(AudioRenderCategory.Media);
    CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings);

    if (result.Status != AudioGraphCreationStatus.Success)
    {
        // Cannot create graph
        return;
    }

    graph2 = result.Graph;

    // Create a device output node
    CreateAudioDeviceOutputNodeResult deviceOutputNodeResult = await graph2.CreateDeviceOutputNodeAsync();

    if (deviceOutputNodeResult.Status != AudioDeviceNodeCreationStatus.Success)
    {

        return;
    }

    deviceOutputNode2 = deviceOutputNodeResult.DeviceOutputNode;

}

}

}

Вы ищете DispatcherQueue.TryEnqueue? Learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/‌​…

Simon Mourier 01.07.2024 07:30

@SimonMourier Если это поможет достичь конечной цели, как это можно реализовать, чтобы приведенный выше код работал?

Giovanni Briones 01.07.2024 07:48

Вы видели Изменение CoreDispatcher.RunAsync на DispatcherQueue.TryEnqueue?

YangXiaoPo-MSFT 01.07.2024 08:00

@YangXiaoPo-MSFT Да, но как это можно адаптировать к этому варианту использования?

Giovanni Briones 01.07.2024 17:58

Не могли бы вы показать минимальный воспроизводимый образец без личной информации?

YangXiaoPo-MSFT 02.07.2024 03:02

@YangXiaoPo-MSFT В основной пост добавлен минимальный воспроизводимый образец без личной информации.

Giovanni Briones 06.07.2024 05:06
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
101
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ничего сложного.

private void FileInputNodeOnFileCompleted(AudioFileInputNode sender, object args)
{
    DispatcherQueue.GetForCurrentThread().TryEnqueue(() =>
    {
        sender.Stop();
        sender.Reset();
    });
}

К сожалению, этот код выдает следующую ошибку: «Ссылка на объект не установлена ​​на экземпляр объекта».

Giovanni Briones 01.07.2024 18:01

Кажется, вы ссылаетесь на объект null. Можете ли вы проверить, какой из них?

Andrew KeepCoding 04.07.2024 10:57

Все проверяется, включая часть кода отправителя, на которую ссылается ненулевой объект AudioFileInputNode.

Giovanni Briones 06.07.2024 04:22
Ответ принят как подходящий

Неудивительно. Меня устраивает.

Обновить код:

bool isQueued = this.DispatcherQueue.TryEnqueue(() =>
{
    sender.Stop();
    sender.Reset();
});

Можете ли вы поделиться кодом в том формате, в котором я поделился кодом в исходном сообщении, вместе со снимком экрана, для всеобщего блага? Спасибо.

Giovanni Briones 08.07.2024 18:32

@GiovanniBriones обновлено. Это почти то же самое, что Измените CoreDispatcher.RunAsync на DispatcherQueue.TryEnqueue.

YangXiaoPo-MSFT 09.07.2024 03:50

@YamgXiaoPo-MSFT Фантастика! Это работает! Спасибо вам большое от всего сердца! Я действительно ценю это! Еще раз спасибо!

Giovanni Briones 10.07.2024 05:56

Другие вопросы по теме