Laden...

Performance probleme...

Erstellt von Taxi4110 vor 18 Jahren Letzter Beitrag vor 18 Jahren 2.529 Views
T
Taxi4110 Themenstarter:in
61 Beiträge seit 2005
vor 18 Jahren
Performance probleme...

hallo jungs,

ich hätte mal eine allgemeine performance frage. in einer andwendung hab ich jetzt einen timer, der jede 2,5 sek das timer_tickevent ausführt. in diesem event holt sich meine anwendung mehrere arrays mit daten. jedes mal, wenn der event ausgelöst wird bleibt nun die anwendung für nicht ganz eine sek. 'eingefroren'. kann ich dieses 'einfrieren' umgehen, indem ich den timer in einen thread auslagere? oder habe ich da was falsch verstanden?

4.221 Beiträge seit 2005
vor 18 Jahren

Nicht den Timer .... sondern den Datenbezug müsstest Du auslagern....

Aber Vorsicht: Aus dem anderen Thread musst Du alle Zugriffe auf das UI in den richtigen Thread marshallen ... Stichwort: ISynchronizeInvoke.Invoke

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo zusammen,

ich denk, wenn man den Timer in einem anderen Thread startet, kommen seine Ticks auch in diesem Thread an. Das wäre also auch eine Möglichkeit.

Aber so oder so. Ein neuer Thread muss auf jeden Fall her. Und dann ist Programmierhans Hinweis zu beachten. Wobei ich es klarer finde, wenn man Control.Invoke sagt. Ist aber Geschmackssache.

herbivore

S
25 Beiträge seit 2005
vor 18 Jahren

Mal ne ganz dumme Frage, habe mittlerweile schon einige Bücher gelesen, aber nirgens ist mir der Begriff "Marshallen" untergekommen. Kann mir das vielleicht mal jemand bitte genauer erläutern ?

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo sharp_noob,

hier geht es darum, dass ein Thread nicht direkt auf die Controls eines anderen Threads zugreifen kann. Deshalb muss er seine Zugriffsanfrage an den Thread weiterleiten, der die Controls erzeugt hat. Dieser führt dann die eigentlichen Zugriffe aus. Dieses Weiterleiten bzw. das Übergeben der Kontrolle von einem Thread an den anderen ist gemeint.

herbivore

S
25 Beiträge seit 2005
vor 18 Jahren

Ok, hab ich verstanden.
Vielen Dank !

P
939 Beiträge seit 2003
vor 18 Jahren

Original von herbivore
Wobei ich es klarer finde, wenn man Control.Invoke sagt. Ist aber Geschmackssache.

Sehe ich auch so. Es gibt nur eine Klasse, die ISynchronizeInvoke implementiert, und zwar System.Windows.Forms.Control.

Das Interface existiert nur, damit Assemblies nicht die System.Windows.Forms.dll referenzieren müssen, um sie unabhängig von Windows Forms zu halten. Direkt im Code verwenden tut man es aber eher selten, finde ich zumindest. Man hantiert eher mit Controls und deren Members.

4.221 Beiträge seit 2005
vor 18 Jahren

Original von Pulpapex

Original von herbivore
Wobei ich es klarer finde, wenn man Control.Invoke sagt. Ist aber Geschmackssache.
Sehe ich auch so. Es gibt nur eine Klasse, die ISynchronizeInvoke implementiert, und zwar System.Windows.Forms.Control.

Das Interface existiert nur, damit Assemblies nicht die System.Windows.Forms.dll referenzieren müssen, um sie unabhängig von Windows Forms zu halten. Direkt im Code verwenden tut man es aber eher selten, finde ich zumindest. Man hantiert eher mit Controls und deren Members.

Da habt ihr zwei schon recht dass es nur eine Klasse gibt die ISynchronizeInvoke implementiert..... aber es gibt jede Menge Klassen (vorallem Component) welche ISynchronizeInvoke verwenden ..... nämlich alle welche ein SynchronizingObject-Property haben..... Meinen eigenen Komponenten verpasse ich oft selber ein SynchronizingObject ... dies sobald diese eigene Threads fahren..... Wenn nun ein Programmierer solche Klassen im Code instanzieren will (statt mit dem Designer) dann finde ich es wichtig, dass man weiss was ISynchronizeInvoke ist... denn erst wenn dieses Property auf eine UI-Komponente gesetzt wird kann die Komponente seine Calls (Events) in den UI-Thread marshallen

Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
Taxi4110 Themenstarter:in
61 Beiträge seit 2005
vor 18 Jahren

*seufz* ok, hab mich jetzt mal bisschen mit threading befasst. dazu hab ich mir ein kleines testprogramm auf der konsole geschrieben:


using System;
using System.Threading;

public class CThread1
{
public void ThreadOne()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Thread: {0}", i)
}
}
}
public class Haupt1
{
public static void Main()
{
CThread1 otto = new CThread1();
Thread thread1 = new Thread(new ThreadStart(otto.ThreadOne));
thread1.Start();
Console.Readline();
}
}

Soweit so gut, jetzt scheitert es aber an der Timerintegration. Wie würde die Lösung aussehen, wenn ich jetzt z.B. die aktuelle Zeit darstellen will? Ich hab versucht einen neuen Timer in Tder Threadausführung zu instanzieren, hab aber weder ein Ergebniss noch eine Exception bekommen.

Mein Beispiel hat so ausgesehen...



namespace threading_sample
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		public System.Windows.Forms.Label label1;
		private System.Windows.Forms.Button button1;
		private System.ComponentModel.IContainer components;
		private System.Threading.Thread givehim;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
			givehim = new Thread(new ThreadStart(doit));

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			this.label1 = new System.Windows.Forms.Label();
			this.button1 = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// label1
			// 
			this.label1.Font = new System.Drawing.Font("Girls are Weird", 15.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.label1.Location = new System.Drawing.Point(32, 24);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(240, 32);
			this.label1.TabIndex = 0;
			this.label1.Text = "label1";
			this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(88, 152);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(112, 24);
			this.button1.TabIndex = 1;
			this.button1.Text = "Start Threading...";
			this.button1.Click += new System.EventHandler(this.button1_Click);
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(292, 266);
			this.Controls.Add(this.button1);
			this.Controls.Add(this.label1);
			this.Name = "Form1";
			this.Text = "Form1";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		private void button1_Click(object sender, System.EventArgs e)
		{
			givehim.Start();
		}
		public void doit()
		{
			System.Windows.Forms.Timer tima = new System.Windows.Forms.Timer();
			tima.Interval = 1000;
			tima.Tick +=new EventHandler(tima_Tick);
			tima.Enabled = true;
			
		}
		private void tima_Tick(object sender, EventArgs e)
		{
			label1.Text = DateTime.Now.ToLongTimeString();
		}
	}
}


P
939 Beiträge seit 2003
vor 18 Jahren

Du bist jetzt genau über diese Invoke-Geschichte gestolpert. Im Thread ausgeführter Code darf nicht direkt auf Windows-Controls zugreifen, sondern muss dafür Invoke verwenden.

private void tima_Tick(object sender, EventArgs e)
{
   // Läuft nicht im UI-Thread, darf so nicht auf label1 zugreifen.
   label1.Text = DateTime.Now.ToLongTimeString();
}

Für dein Beispiel mit dem System.Windows.Forms.Timer ist eigentlich kein zweiter Thread erforderlich (aber du willst ja gerade Threads ausprobieren).

Such mal im Forum nach Control.Invoke oder ISynchronizeInvoke.

_// Edit: _
Zu der Sache, warum keine Exceptions geworfen werden. Exceptions in Threads erzeugen keinen StackTrace, es wird nur der Thread beendet. Deshalb den Code in Threads immer komplett in try-catch-Blöcke einschliessen.

T
Taxi4110 Themenstarter:in
61 Beiträge seit 2005
vor 18 Jahren

langsam bin ich schon am verzweifeln.... könnt ihr hier den fehler entdecken? ich hab das nicht ganz verstanden:


........

    public delegate void dzuuii();

	public class Form1 : System.Windows.Forms.Form
	{
		public System.Windows.Forms.Label label1;
		private System.Windows.Forms.Button button1;
		private System.ComponentModel.IContainer components;
		private System.Threading.Thread givehim;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
			givehim = new Thread(new ThreadStart(doit));

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		
.....

		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		private void button1_Click(object sender, System.EventArgs e)
		{
			givehim.Start();
		}
		public void doit()
		{
			System.Windows.Forms.Timer tima = new System.Windows.Forms.Timer();
			tima.Interval = 1000;
			tima.Tick +=new EventHandler(tima_Tick);
			tima.Enabled = true;			
		}
		public void tima_Tick(object sender, EventArgs e)
		{
			this.BeginInvoke(new dzuuii(this.zuuii2), null);
			//label1.Text = DateTime.Now.ToLongTimeString();
		}
		public void zuuii2()
		{
			this.label1.Text = DateTime.Now.ToLongTimeString();
		}
	}
}


4.221 Beiträge seit 2005
vor 18 Jahren

Obwohl ich mich wiederhole....

Es macht keinen Sinn einen Timer in einem anderen Thread laufen zu lassen

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
Taxi4110 Themenstarter:in
61 Beiträge seit 2005
vor 18 Jahren

ok ok, dann baue ich um. aber ist es denn sinnvoller einen thread durch einen timer zu starten? also bei jedem tick event?

P
939 Beiträge seit 2003
vor 18 Jahren

Du kannst statt des Forms-Timers einen System.Threading.Timer verwenden. Der TimerCallback-Delegat wird ohne Zutun in einem eigenen Thread ausgeführt.

T
Taxi4110 Themenstarter:in
61 Beiträge seit 2005
vor 18 Jahren

jo, supi... jetzt haut es schonmal hin:


private void button1_Click(object sender, System.EventArgs e)
		{
			Thread t = new Thread(new ThreadStart(this.doit));
			t.Name = "Wooorker";
			t.Start();
			//_timer = new System.Threading.Timer(new TimerCallback(this.doit),null,1000,1000);
		}
		public void doit()
		{
			_timer = new System.Threading.Timer(new TimerCallback(this.doit2),null,1000,1000);
			//this.BeginInvoke(new dzuuii(this.zuuii2), null);
			//givehim.Abort();
			//givehim.Join();
		}
		public void doit2(object o)
		{
			this.BeginInvoke(new dzuuii(this.zuuii2), null);
		}
		public void zuuii2()
		{
			this.label1.Text = DateTime.Now.ToLongTimeString();
		}

jetzt muss ich das erlernte nur noch mit meiner anwedung kombinieren... merci euch!!

Original von Pulpapex
Du kannst statt des Forms-Timers einen System.Threading.Timer verwenden. Der TimerCallback-Delegat wird ohne Zutun in einem eigenen Thread ausgeführt.

achso... jetzt. ich bin da ein bisschen durcheinander gekommen, weil mein output nicht angezeigt hat, dass ein zweiter thread beendet wurde; deshalb hab ich das jetzt so gemacht. ich kann ja nochmal umbauen... dankeschön!!

4.221 Beiträge seit 2005
vor 18 Jahren

Und gerne wiederhole ich mich nochmal...

Es macht keinen Sinn einen Timer in einem eigenen Thread laufen zu lassen.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
Taxi4110 Themenstarter:in
61 Beiträge seit 2005
vor 18 Jahren

ja doch... das war doch nur zu testzwecken. ich verschiebe die funktion, die mir mein array holt in den thread, so wie du gesagt hast!

4.221 Beiträge seit 2005
vor 18 Jahren

Schau Dir doch auch noch dieses Beispiel an... auch eine Variante Daten für einen Thread (hier Callback eines Timers) bereitzustellen.....

Methode in der selben Klasse als Thread aufrufen

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
Taxi4110 Themenstarter:in
61 Beiträge seit 2005
vor 18 Jahren

jo, aber jetzt habe ich ein ganz anderes problem. auf einmal findet er eine embedded ressource nicht mehr; ein hintergrundbild!! was kann das sein? ich hab daran nichts geändert!


An unhandled exception of type 'System.Resources.MissingManifestResourceException' occurred in mscorlib.dll


Additional information: Für die angegebene Kultur (oder die neutrale Kultur) in der Assembly konnten keine Ressourcen gefunden werden. Stellen Sie sicher, dass 'Form1.resources' richtig in die Assembly 'NameOne' eingebettet wurde.

//EDIT: er findet jetzt kein bild mehr, dass ich in mein programm eingebettet habe. auch nachdem ich das ganze threading wieder rausgeschmissen habe, tut sich auch nichts. hab auch versucht, erst bild zu entfernen und dann wieder neu einzufügen. bekomme dann wieder fehlermeldung (siehe oben).

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Taxi4110,

wenn es ein ganz anderes Problem ist, solltest du es in einen neuen Thread schreiben.

herbivore