studio - c# timer tick



L'événement Timer ne déclenche pas le clic du bouton (2)

Pas vraiment une réponse, mais voici une version re-factorisée qui n'utilise pas de minuterie. Au lieu de cela, il utilise TaskEx.Delay et async/await TaskEx.Delay , non testés (en ciblant .NET 4.0 avec vs2012 + et Microsoft.Bcl.Async ):

using System;
using System.Collections.Generic;
using System.Windows;
using System.Threading;
using System.Threading.Tasks;

namespace GridTest
{
    /// <summary>
    /// Interaction logic for Window3.xaml
    /// </summary>
    public partial class Window3 : Window
    {
        private static List<string> SourceFiles = new List<string>();
        private static readonly string SourceDir = @"C:\TestFiles\Images\";
        private static readonly string DestinationDir = @"C:\Files\Images\3_5x5\";
        public Window3()
        {
            InitializeComponent();
            this.Loaded += Window3_Loaded;
        }
        void Window3_Loaded(object sender, RoutedEventArgs e)
        {
        }

        async Task DoWorkAsync(CancellationToken token)
        {
            int transferCount;
            for (transferCount = 0; transferCount < SourceFiles.Count; transferCount++)
            {
                token.ThrowIfCancellationRequested();
                var fileName = System.IO.Path.GetFileName(SourceFiles[transferCount]);
                var destFile = System.IO.Path.Combine(DestinationDir, fileName);
                System.IO.File.Copy(SourceFiles[transferCount], destFile, true);
                System.IO.File.Delete(SourceFiles[transferCount]);
                Console.WriteLine(string.Format("Total Files: {0} Number of files transferred: {1}", SourceFiles.Count, transferCount + 1));
                transferCount += 1;

                await TaskEx.Delay(3000, token); // 3s delay
            }
            Console.WriteLine(string.Format("Total number of files transferred: {0}. Transfer Completed", transferCount + 1));
        }

        CancellationTokenSource _cts;
        Task _task;

        private void Start_Click(object sender, RoutedEventArgs e)
        {
            if (_cts != null)
                _cts.Cancel();
            _cts = new CancellationTokenSource();
            _task = TaskEx.Run(() => DoWorkAsync(_cts.Token), _cts.Token);
        }

        private void Stop_Click(object sender, RoutedEventArgs e)
        {
            if (_cts != null)
                _cts.Cancel();
        }
    }
}

J'essaye de transférer le Image file pour chaque 3 secondes de la source au répertoire de destination, quand je clique sur le bouton "Démarrer" . Et "Stop" bouton est pour arrêter le transfert de fichiers.

Si j'utilise le bouton Démarrer pour la troisième fois, l'événement ne se déclenche pas; Ainsi, les fichiers ne sont pas transférés.

Le progrès que j'ai fait est dans le ci-dessous:

  1. Démarrer --- Transfert de fichier; Appuyez sur le bouton STOP // Cela fonctionne aussi bien.
  2. Démarrer --- Transfert de fichier; Appuyez sur le bouton STOP // Cela fonctionne aussi.
  3. Démarrer ----- Le fichier ne se transfère pas, l' Event is not firing // Ça ne marche pas!

Ce que j'ai fait pour résoudre le problème:

  • Je mets un point de rupture dans l'événement Tick et l'événement tick ne tire pas.
  • J'ai vérifié que SourceFiles.Count est supérieur à TransferCount (SourceFiles.Count> TransferCount) .
  • J'ai remarqué que pendant le transfert de fichier, si je clique sur le bouton Arrêter pendant un transfert de fichier ce fichier particulier reste non transféré.

Comment puis-je réparer cela? Merci d'avance.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Threading;

namespace GridTest
{
    /// <summary>
    /// Interaction logic for Window3.xaml
    /// </summary>
    public partial class Window3 : Window
    {
        DispatcherTimer dispatcherTimer = new DispatcherTimer();
        private static List<string> SourceFiles = new List<string>();
        private static readonly string SourceDir = @"C:\TestFiles\Images\";
        private static readonly string DestinationDir = @"C:\Files\Images\3_5x5\";
        private static int TransferCount = 0;
        public Window3()
        {
            InitializeComponent();
            this.Loaded += Window3_Loaded;
        }
        void Window3_Loaded(object sender, RoutedEventArgs e)
        {
            dispatcherTimer.Interval = new TimeSpan(0, 0, 3);
            dispatcherTimer.Tick += dt_Tick;
        }
        void dt_Tick(object sender, EventArgs e)
        {
            if (TransferCount < SourceFiles.Count)
            {
                var fileName = System.IO.Path.GetFileName(SourceFiles[TransferCount]);
                var destFile = System.IO.Path.Combine(DestinationDir, fileName);
                System.IO.File.Copy(SourceFiles[TransferCount], destFile,true);
                System.IO.File.Delete(SourceFiles[TransferCount]);
                Console.WriteLine(string.Format("Total Files: {0} Number of files transferred: {1}", SourceFiles.Count, TransferCount + 1));
                TransferCount += 1;
            }
            else
            {
                Console.WriteLine(string.Format("Total number of files transferred: {0}. Transfer Completed", TransferCount + 1));
                (sender as DispatcherTimer).Stop();
                (sender as DispatcherTimer).Tick -= dt_Tick;
            }
        }

        private void Start_Click(object sender, RoutedEventArgs e)
        {
            if (!System.IO.Directory.Exists(DestinationDir))
            {
                System.IO.Directory.CreateDirectory(DestinationDir);
            }

            if (System.IO.Directory.Exists(SourceDir))
            {
                SourceFiles = Directory.GetFiles(SourceDir).ToList();
            }
        }

        private void Stop_Click(object sender, RoutedEventArgs e)
        {
            dispatcherTimer.Stop();
        }
    }
}

Si vous appelez Stop, votre événement timer ne doit pas se déclencher tant que vous n'avez pas défini la propriété IsEnabled sur true.
Donc je suggère de faire un peu de refactoring

    void Window3_Loaded(object sender, RoutedEventArgs e)
    {
        LoadSourceFiles();
        StartTimer();
    }
    void StartTimer()
    {
        dispatcherTimer.Interval = new TimeSpan(0, 0, 3);
        dispatcherTimer.Tick += dt_Tick;
        dispatcherTimer.IsEnabled = true;
    }
    void LoadSourceFiles()
    {
        if (!System.IO.Directory.Exists(DestinationDir))
        {
            System.IO.Directory.CreateDirectory(DestinationDir);
        }

        if (System.IO.Directory.Exists(SourceDir))
        {
            SourceFiles = Directory.GetFiles(SourceDir).ToList();
        }
    }

et appelez cette méthode chaque fois que vous appuyez sur le bouton Démarrer

    private void Start_Click(object sender, RoutedEventArgs e)
    {
        StartTimer();
    }

    private void Stop_Click(object sender, RoutedEventArgs e)
    {
        dispatcherTimer.IsEnabled = false;
    }

Je suggère également de réinitialiser la variable globale qui garde la trace des fichiers transférés à zéro quand à l'intérieur de l'événement Tick vous découvrez que chaque fichier a été transféré (ou désactiver le bouton Démarrer)

    ....
    else
    {
          Console.WriteLine(string.Format("Total number of files transferred: {0}. Transfer Completed", TransferCount + 1));
          (sender as DispatcherTimer).Stop();
          (sender as DispatcherTimer).Tick -= dt_Tick;
          TransferCount = 0;
    }

Sinon, si vous redémarrez la minuterie dans cette situation, elle s'arrêtera immédiatement