Question

J'ai besoin d'un équivalent de minuterie qui exécutera périodiquement certaines actions spécifiques (par exemple une mise à jour de quelques progrès dans la base de données ou de la vérification des nouveaux travaux à exécuter dans une base de données).

Ces actions sont liées à un waihandle qui spécifie si le travail doit être exécuté ou non. Donc, fondamentalement, cela pourrait être, par exemple, un atarofortezEvent défini de l'extérieur lorsqu'il existe une nouvelle entité dans une base de données et déclenche la recherche de ces nouvelles entités. La minuterie est nécessaire car je souhaite limiter le nombre de requêtes à la base de données. Donc, si 10 nouvelles notifications arrivent, la réestification automatique ne sera définie qu'une fois et il n'y aura aussi qu'une seule requête pour tous.

Mes premières tentatives ressemblent à ceci:

class ConditionalScheduler
{
    public void AddConditionalAction(WaitHandle handle, Action action)
    {
        lock (syncRoot)
        {
            handles.Add(handle);
            actions.Add(handle, action);
        }
    }

    private readonly object syncRoot = new object();

    private readonly Dictionary<WaitHandle, Action> actions = new Dictionary<WaitHandle, Action>();
    private readonly List<WaitHandle> handles = new List<WaitHandle>();

    public void RunTimerLoop()
    {
        do
        {
            WaitHandle[] waitHandles = handles.ToArray();
            int index = WaitHandle.WaitAny(waitHandles);

            if (index >= 0)
            {
                WaitHandle handle = waitHandles[index];

                Action action;
                lock (syncRoot)
                {
                    action = actions[handle];
                }

                action();
            }
            Thread.Sleep(5000);
        } while (true);
    }

Le problème avec cette approche est que Waithandle.Waitany ne me donnera que l'index du premier waithandle déclenché. Donc, si j'ai 2 personnes ou plus qui sont déclenchées, je n'utiliserai que les premières actions et non les autres.

Avez-vous une meilleure conception pour atteindre les résultats requis d'exécution de toutes les actions qui ont été déclenchées dans la période spécifiée? Si cela simplifie la matière, je pourrais utiliser un autre type de mécanisme de notification au lieu de waitvulles.

merci!

Était-ce utile?

La solution

Peut-être que vous pourriez aller avec une file d'attente à deux fil / exécution en vrac? Notez que le code vers le bas est juste un concept que j'écris sans studio visuel, donc je fais sur une liste, cela ferait mieux d'être fait avec une file d'attente, mais je ne me souviens pas de la syntaxe sans IntelliSense :) ...

private readonly Dictionary<WaitHandle, Action> actions = new Dictionary<WaitHandle, Action>();
    private readonly List<WaitHandle> handles = new List<WaitHandle>();
    private readonly List<WaitHandle> triggeredHandles = new List<WaitHandle>();

// thread 1
    public void CheckLoop()
    {
        do
        {
            WaitHandle[] waitHandles = handles.ToArray();
            int index = WaitHandle.WaitAny(waitHandles);

            if (index >= 0)
            {
                lock (triggeredHandles)
                {
                   triggeredHandles.Add(waitHandles[index]);
                }

            }            
        } while (true);
    }

// thread 2
public void RunLoop()
    {
        do
        {
            lock(triggeredHandles)
            {
                foreach (var th in triggeredHandles) {

                   Action action;
                   lock (syncRoot)
                   {
                       action = actions[th];
                   }

                   action();                   
                }
                triggeredHandles.Clear();
            }
            Thread.Sleep(5000);
        } while (true);
    }

Autres conseils

Avez-vous envisagé d'utiliser les classes de minuterie intégrées? GeneraCoDeTagCode est une implémentation de poids léger qui utilise le System.Threading.Timer, ou generAccodiceCode qui fournit des événements connexes et plus de fonctionnalités.

Vous vous sauverrez probablement beaucoup de tracas en utilisant Extensions réactives (RX) - Il a beaucoup de grandes façons de composer des événements de la manière que vous demandez.

Ce site est une façon pratique de voir le type de choses que Rx peut faire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top