NAS

C# Schleife in zeitl. Abhängigkeit ausführen lassen

estre

Commander
Registriert
Dez. 2005
Beiträge
3.006
Hey,

ich möchte eine Schleife programmieren die 5 Sekunden lang durchläuft und alle 0,5 Sekunden ausgeführt wird (also insgesamt 10mal). Der zeitliche Faktor ist ziemlich wichtig, da ich mit der Schleife überwachen möchte wie sich ein bestimmter Wert über eine bestimtme Zeitspanne verändert.

Kann man das programmatisch umsetzen? :)

Danke für eure Hilfe!

Grüße
 
Alternativ kann man kann ja Threads auch eine Weile schlafen legen, die Frage ist wie exakt deine Zeitfenster sein müssen...
 
Welcher Wert? In deinem Programm kannst du den Debugger nutzen und einen Breakpoint setzen.
 
Hey,

danke für Eure Antworten.

@MrStools
Korrigiere mich wenn ich falsch liege, aber in deinem Beispiel wird doch einfach nur ein Timer gestartet und nach Ablauf dieses Timers der Code ausgeführt, doer nicht ?

@Yuuri:
Ich möchte die Aufrufzeiten von COM+-Anwendungen überwachen und diese recyclen wenn ein bestimmter Wert überschritten wurde. Das Problem ist, dass die Aufrufzeit einer Komponente durchaus für einige Sekunden mal ziemlich hoch sein kann. Meine Idee ist es nun die Aufrufzeiten über 5 Sek zu tracken und den Mittelwert zu bestimmten. Ist der Mittelwert über dem vorgegebenen Schwellwert wird die Komponente recyclet, ansonsten eben nicht.

Für bessere Ideen bin ich gerne offen :9

Grüße
 
in deinem Beispiel wird doch einfach nur ein Timer gestartet und nach Ablauf dieses Timers der Code ausgeführt

..und wenn man das in eine Schleife packt..


Ich geh jetzt raus hier mangels Ahnung, dachte das ist so oder so eine gute Anlaufstelle für dich.
 
MrStools schrieb:

MrStools schrieb:
..und wenn man das in eine Schleife packt..


Ich geh jetzt raus hier mangels Ahnung, dachte das ist so oder so eine gute Anlaufstelle für dich.

Das ist der richtige Ansatz, damit der Timer nach 10 durchläufen beendet wird brauchst doch nur noch ne Variable hochzählen und wenn diese 10 erreicht rufst die Methode timer.Stop() auf.

Brauchst aber keine Schleife da die Tick Methode immer wieder aufgerufen wird bis dieser eben durch Stop beendet wird.

Also...
Code:
Timer t1 = new Timer();
t1.Interval = 500; // 500 ms = 0,5 Sekunden
t1.Tick+=new EventHandler(t1_Tick); //Diese Methode wird dann alle 0,5 Sekunden aufgerufen
t1.Start(); // Timer starten

int timerCount = 0;
void t1_Tick(object sender, EventArgs e)
{
   timerCount++;
   if (timerCount > 10) {
        t1.Stop(); //beendet den Timer nach 10 durchgängen (also 10 Sekunden)
        return;
   }

   //Hier dein Code zum auslesen des COM Values..
}
 
Hey,

zunächst noch einmal vielen Dank für Eure Hilfe!


So ganz habe ich das noch nicht verstanden.
Diese t1_Tick MEthode kommt ja dann in meine Klasse und die Erzeugung des Timer-Objektes geschieht z.B. in meiner Main-Methode, oder ?
Das Problem ist, dass die Eigenschaft t1.Tick rot unterkringelt wird, scheinbar gibt es das so nicht.
die using Direktiven (System.Timers.Timer) müssten alle vorhanden sein.


und auch die Variable int timerCount steht ja außerhalb meiner MEthode, müsste ich diesen Wer nicht irgendwo übergeben ?
Grüße
 
Zu eins, der using Verweis fehlt ;) sagt der Fehler ja schon. Es kommt auch darauf an, ob du in einem WinForms- oder WPF-Projekt arbeitest.
WPF==DispatcherTimer and Windows Forms==Forms.Timer.
Beispiel:
Code:
class blub
    {
        System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();

        public blub()
        {
            timer.Interval = TimeSpan.FromSeconds(0.1);
            timer.Tick += timer_Tick;
        }

        public void startTimer()
        {
            timer.Start();
        }

        int counter;
        void timer_Tick(object sender, EventArgs e)
        {
            counter++;
            if (counter == 10)
            {
                timer.Stop();
            }
            //todo
        }
    }
ggf. noch den "counter" zurücksetzen.

#Edit: Noch zur zweiten Frage: Der "counter" zählt aktuell, nach deiner Fragestellung nur bis 10, also zehn mal soll überprüft werden. Wenn du das ganze etwas variabler machen willst, kann du diesen auch setzen. Dafür am besten dann eine Property von "counter" machen oder direkt im Konstruktor setzen.
 
Zuletzt bearbeitet:
Dispatcher und Forms Timer sind beide nicht geeignet in diesem Fall, da es UI Timer sind und der TE schon sagte, dass es unter Umständen länger dauern kann, bis er ein Ergebnis hat.

Zum Thema. Versuch folgendes (Achtung ungetestet, sollte aber funktionieren ;))

Code:
namespace YourNamespace
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    
    // .NET < 4.5: System.Runtime.CompilerServices entfernen
    using System.Runtime.CompilerServices;
    using System.Timers;

    internal sealed class MeasureEventArgs : EventArgs
    {
        public double Result { get; private set; }

        public MeasureEventArgs( double result )
        {
            Result = result;
        }
    }

    internal sealed class AverageTimeCalculator : INotifyPropertyChanged, IDisposable
    {
        #region Fields

        private readonly Timer _timer;

        private uint _iterations;

        private readonly List<double> _extensions;

        private double _average;

        private Func<double> _doMeasure;

        #endregion

        #region Constructor

        public AverageTimeCalculator()
        {
            _extensions = new List<double>();
            _timer = new Timer();
            _timer.Elapsed += OnTimerTick;
        }

        #endregion
        
        #region Events

        public delegate void MeasureEventhandler( object sender, MeasureEventArgs e );

        public event MeasureEventhandler Measured;

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Properties

        public double Average
        {
            get
            {
                return _average;
            }

            private set
            {
                if ( !_average.Equals( value ) )
                {
                    _average = value;

                    // .NET >= 4.5
                    RaisePropertyChanged();
                    
                    // .NET < 4.5
                    //RaisePropertyChanged( "Average" );
                }
            }
        }

        public bool IsActive { get { return _timer.Enabled; } }

        #endregion

        #region Public Methods

        public void Dispose()
        {
            if ( _timer.Enabled )
            {
                _timer.Stop();
            }

            _timer.Dispose();
        }

        public void Run( double interval, uint iterations, Func<double> measure )
        {
            if ( _timer.Enabled )
            {
                _extensions.Clear();
                Average = 0;
                _timer.Stop();
            }

            _doMeasure = measure;
            _timer.Interval = interval;
            _iterations = iterations;
            _timer.Start();

            RaisePropertyChanged( "IsActive" );
        }

        #endregion

        #region Methods

        private void OnTimerTick( object sender, ElapsedEventArgs e )
        {
            _extensions.Add( _doMeasure.Invoke() );
            Average = _extensions.Average();
            _iterations--;

            if ( _iterations < 1 )
            {
                _timer.Stop();
                RaiseMeasured( new MeasureEventArgs( Average ) );
                RaisePropertyChanged( "IsActive" );
            }
        }

        private void RaiseMeasured( MeasureEventArgs e )
        {
            MeasureEventhandler handler = Measured;
            if ( handler != null )
            {
                handler( this, e );
            }
        }

        // .NET < 4.5
        // public void RaisePropertyChanged( string propertyName )
        // .NET >= 4.5
        private void RaisePropertyChanged( [CallerMemberName] string propertyName = null )
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if ( handler != null )
            {
                PropertyChangedEventArgs e = new PropertyChangedEventArgs( propertyName );
                handler( this, e );
            }
        }

        #endregion
    }
}

Verwendung:

Code:
public MainWindow()
{
    InitializeComponent();

    AverageTimeCalculator calculator = new AverageTimeCalculator();
    calculator.Measured += OnAverageReceived;
            
    // zwischenergebnis kann über calculator.Average abgefragt werden.


    Func<double> calculateAverage = () =>
                                        {
                                            double time = 0;
                                            // calculate time
                                            return time;
                                        };

    calculator.Run( 500, 10, calculateAverage );
}

private void OnAverageReceived( object sender, MeasureEventArgs e )
{
    double averageTime = e.Result;
    // average irgendwo anzeigen...
}
 
Zuletzt bearbeitet:
Ich habe eben den Code oben geupdatet. Prinzipiell hat er funktioniert, aber man musste unötigerweise einen Tick zu lange auf das Ergebnis (Event Measured) warten.
 
Zurück
Oben