PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C# - Simpler Countdown als Konsolen-Anwendung?


Siegfried
2007-11-01, 08:33:00
ich lerne seit 1-2monaten c# und wollte mal ein programm schreiben dass ich auch benutze
es soll eine konsolenanwendung sein die 65minuten runterzaehlt und sich dann beendet
die minuten sollen dabei in der konsole angezeigt werden
oder was noch besser waere in der titelleiste
hat jemand ein tipp fuer mich wie ich das am besten mache?
koennte das wohl mit ner schleife und sleep machen was aber sicher nicht so optimal ist ;)

gr@fz@hL
2007-11-01, 09:02:24
Ich bin jetzt zwar nicht soo der C#-Profi, aber im Prinzip würde ich es genau so machen - nur mit einem Timer-Objekt statt der Thread.Sleep()-Methode :wink:
Auch ein Link dazu: http://www.csharphelp.com/archives/archive90.html

Monger
2007-11-01, 09:33:23
Sleep ist bäh, weil du dir nicht sicher sein kannst, wann dein Thread aufgeweckt wird, und wieviel Rechenzeit dir das Betriebssystem lässt. Unter Volllast würden deine 65 Minuten deutlich länger dauern als im Leerlauf, und das kann ja nicht der Sinn der Sache sein...

Sauberer ist es tatsächlich, ein Timer Objekt zu verwenden, dass jede Minute ein passendes Ereignis auf die Konsole feuert, und nach x Durchläufen sich und die Konsole beendet. Wobei ich mir das auf ner Konsole vergleichsweise kompliziert vorstelle. Mit ner echten Windows Applikation sind das nur ein paar Klicks.

Siegfried
2007-11-01, 10:24:58
bei objekten bin ich noch nicht ganz :tongue:
mache nur alle paar tage mal was

haette am liebsten ne int variable die ein timer ist

gr@fz@hL
2007-11-01, 14:37:21
Sorry, aber dann solltest du dich schnellstens mit Objekten vertraut machen - ohne geht in C# eigentlich gar nix (mich wundert ehrlich gesagt, wie du zwei Monate ohne ausgekommen bist :wink:).

MuLuNGuS
2007-11-01, 17:24:03
vorsicht,
dieses beispiel gilt nur als denkanstoss da eben schnell hingekloppt:

an der kommandozeile kann man stunden minuten und sekunden als dauer angeben, wenn das fenster für 20 minuten und 30 sekunden aktiv sein soll is die exe folgendermaßen zu starten:

timer.exe 0 20 30

die abgelaufene zeit wird im fenster und im titel wiedergegeben.(sollte alles selbsterklärend sein)

na dann, viel spaß ;)


class main
{

static void Main(string[] args)
{

TimeSpan duration = new TimeSpan(Convert.ToInt32(args[0]), Convert.ToInt32(args[1]), Convert.ToInt32(args[2]));
DateTime dtstart = DateTime.Now;
double seconds = 0;
double lastseconds = 0;


for(;;)
{
DateTime dtlast = DateTime.Now;
TimeSpan diff = new TimeSpan();
diff = dtlast - dtstart;

seconds = diff.TotalSeconds - diff.TotalSeconds % 1;
if (seconds > lastseconds)
{
Console.Title = diff.ToString();
Console.WriteLine(diff);
lastseconds = seconds;
}


if (diff > duration)
break;

Thread.Sleep(1000);
}

}
}

gr@fz@hL
2007-11-01, 18:15:51
Codebeispiel

Dann nutzt du aber wieder die Sleep()-Methode...

Gast
2007-11-01, 18:30:47
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace Timer
{
class Program
{
private static System.Timers.Timer myTimer = null;
private static int myStartMinute = 0;
private static ManualResetEvent myResetEvent = null;

static void Main( string[] args )
{
myStartMinute = 65;

myResetEvent = new ManualResetEvent( false );

myTimer = new System.Timers.Timer();
myTimer.Interval = 60000;

myTimer.Elapsed += new System.Timers.ElapsedEventHandler( myTimer_Elapsed );

Console.WriteLine( myStartMinute.ToString() );
myTimer.Start();

myResetEvent.WaitOne();

Console.WriteLine( "Programm beenden" );
}

static void myTimer_Elapsed( object sender, System.Timers.ElapsedEventArgs e )
{
myStartMinute -= 1;


if (myStartMinute == 0)
myResetEvent.Set();
else
Console.WriteLine( myStartMinute.ToString() );
}
}
}

del_4901
2007-11-01, 18:54:10
Dann nutzt du aber wieder die Sleep()-Methode...
Ja ist ja auch richtig. Er soll ja nicht die ganze Zeit CPU Zeit verpratzen.
Augen auf im Straßenverkehr.

MuLuNGuS
2007-11-01, 18:55:33
Dann nutzt du aber wieder die Sleep()-Methode...

ist wie gesagt nur ein denkanstoss, es funktioniert ja auch völlig ohne Sleep() methode, nur das die auslastung dann 100% beträgt. man muß ja auch nicht alles vorkauen ;)

Monger
2007-11-01, 18:58:19
Ja ist ja auch richtig. Er soll ja nicht die ganze Zeit CPU Zeit verpratzen.
Augen auf im Straßenverkehr.
Das ist eine zu optimistische Annahme. Damit nimmst du insgeheim an, dass nix anderes auf dem Rechner läuft! ;)

Wenn irgendwas anderes die Rechenlast nach oben treibt, wird das Betriebssystem den Thread deines Programms pausieren, und damit wird ein Durchlauf deutlich länger als ne Sekunde.

Die einzige halbwegs zuverlässige Methode für Zeitabläufe ist, sich an der Systemuhr zu orientieren, und genau das macht auch ein Timer.

MuLuNGuS
2007-11-01, 20:14:38
Das ist eine zu optimistische Annahme. Damit nimmst du insgeheim an, dass nix anderes auf dem Rechner läuft! ;)

Wenn irgendwas anderes die Rechenlast nach oben treibt, wird das Betriebssystem den Thread deines Programms pausieren, und damit wird ein Durchlauf deutlich länger als ne Sekunde.

Die einzige halbwegs zuverlässige Methode für Zeitabläufe ist, sich an der Systemuhr zu orientieren, und genau das macht auch ein Timer.


ebenso DateTime.Now, auf was willst du also hinaus?

Monger
2007-11-01, 20:50:39
ebenso DateTime.Now, auf was willst du also hinaus?
Deine Lösung ist ein bißchen geschickter, wenn auch nicht perfekt. Du kriegst unter Umständen ein etwas ungleichmäßiges Ticken, aber wenigstens ist die Zeit richtig.


Wie gesagt: beste Lösung ist, sich einen Timer zu holen und dafür einen passenden Event Listener zu schreiben. Elegant, einfach und sehr präzise.

MuLuNGuS
2007-11-01, 21:26:57
jau,

auch wenn die letzte sekunde je nach startzeitpunkt ungenau gezeigt wird...ist auch banal darum ging es dem threadstarter denk ich mal nicht ;)

Siegfried
2007-11-01, 22:22:45
vorsicht,
dieses beispiel gilt nur als denkanstoss da eben schnell hingekloppt:

an der kommandozeile kann man stunden minuten und sekunden als dauer angeben, wenn das fenster für 20 minuten und 30 sekunden aktiv sein soll is die exe folgendermaßen zu starten:

timer.exe 0 20 30

die abgelaufene zeit wird im fenster und im titel wiedergegeben.(sollte alles selbsterklärend sein)

na dann, viel spaß ;)
danke das funktioniert schonmal gut
ein paar sachen sind nicht so optimal
aber das aender ich wenn ich den kompletten code verstehe
args etc sagt mir jetzt noch nichts

hab das mal so gemacht dass es compiled
using System;

class main
{

static void Main(string[] args)
{

TimeSpan duration = new TimeSpan(Convert.ToInt32(args[0]), Convert.ToInt32(args[1]), Convert.ToInt32(args[2]));
DateTime dtstart = DateTime.Now;
double seconds = 0;
double lastseconds = 0;


for(;;)
{
DateTime dtlast = DateTime.Now;
TimeSpan diff = new TimeSpan();
diff = dtlast - dtstart;

seconds = diff.TotalSeconds - diff.TotalSeconds % 1;
if (seconds > lastseconds)
{
Console.Title = diff.ToString();
Console.WriteLine(diff);
lastseconds = seconds;
}


if (diff > duration)
break;

System.Threading.Thread.Sleep(1000);
}

}
}
wundert mich dass System.Threading.Thread.Sleep nicht ohne System geht
obwohl ich using System; geschrieben hab

Siegfried
2007-11-01, 22:27:14
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace Timer
{
class Program
{
private static System.Timers.Timer myTimer = null;
private static int myStartMinute = 0;
private static ManualResetEvent myResetEvent = null;

static void Main( string[] args )
{
myStartMinute = 65;

myResetEvent = new ManualResetEvent( false );

myTimer = new System.Timers.Timer();
myTimer.Interval = 60000;

myTimer.Elapsed += new System.Timers.ElapsedEventHandler( myTimer_Elapsed );

Console.WriteLine( myStartMinute.ToString() );
myTimer.Start();

myResetEvent.WaitOne();

Console.WriteLine( "Programm beenden" );
}

static void myTimer_Elapsed( object sender, System.Timers.ElapsedEventArgs e )
{
myStartMinute -= 1;


if (myStartMinute == 0)
myResetEvent.Set();
else
Console.WriteLine( myStartMinute.ToString() );
}
}
}


da kommt bei mir: The type or namespace name 'Timers' does not exist in the namespace 'System' (are you missing an assembly reference?) (CS0234)
compiler is sharpdevelop

Gast
2007-11-02, 00:52:22
da kommt bei mir: The type or namespace name 'Timers' does not exist in the namespace 'System' (are you missing an assembly reference?) (CS0234)
compiler is sharpdevelop

Hab jetzt extra wegen dir Sharpdevelop installiert (neuste Version)

und den Code aus meienn Post rauskopiert und er rennt einwandfrei so wie er es aus VS2005 tut.

Irgendwas machst du wohl falsch ;)

MuLuNGuS
2007-11-02, 10:56:16
wundert mich dass System.Threading.Thread.Sleep nicht ohne System geht
obwohl ich using System; geschrieben hab

vielleicht hätte ich meine using anweisungen mitposten sollen.

aber so macht man sich gedanken darüber wieso das dann so und so ist ;)

wenn du den namespace:

using System.Threading;

hinzufügst kannst du einfach:

Thread.Sleep(1000);

schreiben da die klasse "Thread" unter dem namespace System.Threading zu verfügung steht.

also:

"System" ist ein namespace ebenso wie "Threading" ein namespace ist, nur das sich "Threading" wieder unterhalb von "System" befindet.

alles klar?
®

MuLuNGuS
2007-11-02, 11:01:57
ach übrigens!!!

wenn man diese beiden namespaces nutzt:

using System.Windows.Forms;

using System.Threading;

dann gibt es eine NAMEN-MEHRDEUTIGKEIT da die klasse "Timer" innerhalb von beiden existiert, also muß man sich mit dem voll-qualifizierten namen für einen von beiden entscheiden mit:

System.Windows.Forms.Timer;

oder:

System.Threading.Timer;

VS2005 gibt aber einen hinweis auf diesen umstand.
®

Elemental
2007-11-04, 11:41:51
Und immer schön auf die Unterschiede der 3 verschiedenen Timer achten ;)

http://msdn.microsoft.com/msdnmag/issues/04/02/TimersinNET/default.aspx

Besonder gut find ich diese Übersicht, Figure 7:
http://msdn.microsoft.com/msdnmag/issues/04/02/TimersinNET/default.aspx?loc=&fig=true#fig7