Home > OS >  Disable a button, when a Task is completed
Disable a button, when a Task is completed

Time:10-23

I have a method, that checks if a button can be pressed or not, if my file path or the language is null, I don't enable the button, and of course, when my file path is selected, I raise the event.

So right now I am doing some work on Azure, and I want to disable the button when I start my work and enable it when I finished my work.

I tried to raise the event, before the call o the method and after the call, but it doesn't enable the button

        public string? FilePath { get; set; }

        public bool IsWorking { get; set; }

        public Dictionary<int, Languages>? LanguagesDictionary { get; set; }

        public Visibility CanShow { get; set; }

        public DialogHelper DialogHelper { get; }

        public FolderHelper FolderHelper { get; }

        public AudioHelper AudioHelper { get; }

        public AzureTranscriptionService AzureTranscription { get; }

        public Command PickFileCommad { get; set; }

        public Command StartCommand { get; set; }

        private string? _SelectedItem;

        public string SelectedItem {
            get => _SelectedItem!;
            set {
                if (_SelectedItem != value) {
                    _SelectedItem = value;
                    StartCommand.RaiseCanExecuteChanged();
                }
            }
        }

        public AudioPageViewModel() {
            InitListLanguages();
            AzureTranscription = new AzureTranscriptionService();
            DialogHelper = new DialogHelper();
            FolderHelper = new FolderHelper();
            AudioHelper = new AudioHelper();
            CanShow = Visibility.Hidden;
            PickFileCommad = new Command(PickFileAction);
            StartCommand = new Command(StartAction, CanStartAction);
        }

        private bool CanStartAction(object arg) {
            if (string.IsNullOrEmpty(SelectedItem) ||
                string.IsNullOrEmpty(FilePath) ||
                IsWorking == true) {
                return false;
            }
            return true;
        }

        private async void StartAction(object obj) {

            var FileWithoutExtension = Path.GetFileNameWithoutExtension
                (FilePath);

            var AudioPath = FolderHelper.CreateFolder(ConstantsHelpers.AUDIO);

            var DocumentPath = FolderHelper.CreateFolder();

            var AudioFileNamePath = Path.Combine(AudioPath, $"{FileWithoutExtension}{ConstantsHelpers.WAV}");

            var ConvertedAudioPath = AudioHelper.Converter(FilePath!, AudioFileNamePath);

            var DocumentName = Path.Combine(DocumentPath, $"{FileWithoutExtension}{ConstantsHelpers.DOCX}");

            IsWorking = true;

            StartCommand.RaiseCanExecuteChanged();

            await AzureTranscription.ConvertToTextAsync(ConvertedAudioPath,
                SelectedItem, DocumentName);

            IsWorking = false;
            StartCommand.RaiseCanExecuteChanged();


        }

        private void PickFileAction() {
            var FullPath = DialogHelper.GetFilePath(ConstantsHelpers.AUDIO);
            FilePath = FullPath;

            StartCommand?.RaiseCanExecuteChanged();
        }

 public async Task ConvertToTextAsync(
            string FilePath,
            string Language,
            string WordDocName) {

            // Configure speech service

            var config = SpeechConfig.FromSubscription(ConstantsHelpers.AZURE_KEY, ConstantsHelpers.AZURE_REGION);
            config.SpeechRecognitionLanguage = Language;
            // Configure speech recognition

            var taskCompleteionSource = new TaskCompletionSource<int>();

            using var audioConfig = AudioConfig.FromWavFileInput(FilePath);
            using var speechRecognizer = new SpeechRecognizer(config, audioConfig);
            speechRecognizer.Recognizing  = SpeechRecognizer_Recognizing;
            speechRecognizer.Recognized  = SpeechRecognizer_Recognized;
            speechRecognizer.SessionStarted  = SpeechRecognizer_SessionStarted;
            speechRecognizer.SessionStopped  = SpeechRecognizer_SessionStopped;

            await speechRecognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);

            Task.WaitAny(new[] { taskCompleteionSource.Task });

            await speechRecognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);
        }

        private void SpeechRecognizer_SessionStopped(object? sender, SessionEventArgs e) {

            Debug.WriteLine("Stepped");
            var sb = new StringBuilder();

            foreach (var item in Letters) {
                sb.Append(item);
            }
        }

        private void SpeechRecognizer_SessionStarted(object? sender, SessionEventArgs e) {

            Debug.WriteLine("Started");
        }
        private void SpeechRecognizer_Recognized(object? sender, SpeechRecognitionEventArgs e) {
            if (e.Result.Reason == ResultReason.RecognizedSpeech) {
                foreach (var item in e.Result.Text) {
                    Letters.Add(item);
                }
            }
        }

        private void SpeechRecognizer_Recognizing(object? sender, SpeechRecognitionEventArgs e) {

            Debug.WriteLine(e.Result.Text);
        }
    }

When I start working, I execute this code

Many thanks

CodePudding user response:

If the below refactorings don't help, debug your program:

  • check if CanStartAction is actually called and returns the expected result.
  • probably the asynchronous method returns too fast for your eye to see the button being disabled. Modify your code as follows to test this:
await AzureTranscription.ConvertToTextAsync(ConvertedAudioPath,
                SelectedItem, DocumentName);
await Task.Delay(TimeSpan.FromSeconds(5));

In general, move the RaiseCanExecuteChanged request to the relevant property setters to keep your code clean.


private bool isBusy;
private bool IsBusy 
{ 
  get => this.isBusy; 
  set
  {
    this.isBusy = value;
    this.StartCommand.RaiseCanExecuteChanged();
  }
}

private bool CanStartAction(object arg) 
{
  return !string.IsNullOrEmpty(SelectedItem) &&
    !string.IsNullOrEmpty(FilePath) &&
    !this.IsBusy
}

private async void StartAction(object obj) 
{ 
  this.IsBusy = true;

  var fileWithoutExtension = Path.GetFileNameWithoutExtension
                (FilePath);
  var audioPath = FolderHelper.CreateFolder(ConstantsHelpers.AUDIO);
  var documentPath = FolderHelper.CreateFolder();
  var audioFileNamePath = Path.Combine(audioPath, $"{FileWithoutExtension}{ConstantsHelpers.WAV}");
  var convertedAudioPath = AudioHelper.Converter(FilePath!, audioFileNamePath);
  var documentName = Path.Combine(documentPath, $"{fileWithoutExtension}{ConstantsHelpers.DOCX}");

  await AzureTranscription.ConvertToTextAsync(convertedAudioPath,
                this.SelectedItem, documentName);

  this.IsBusy = false;
}

public async Task ConvertToTextAsync(string FilePath,
  string Language,
  string WordDocName) 
{
  ...
  
  // Using Task.Wait, Task.WaitAny and Task.WaitAll will execute a Task synchronously and introduces a potential deadlock.
  // To avoid this, always await a Task and use Task.WhenAny and Task.WhenAll instead
  await Task.WhenAny(new[] { taskCompleteionSource.Task });
  
  // Or because you only have to wait for a single Task write
  await taskCompleteionSource.Task;

  ...
}

See C# Naming guidelines

  •  Tags:  
  • wpf
  • Related