Jump to content

C#.Net und COM Events


tausi

Recommended Posts

Hallo allerseits!

 

Ich versuche zur Zeit in einer C# Anwendung (2005Express) die Events vom DVBViewer zu bekommen.. leider funktioniert das nicht so wie ich es gewohnt bin -> es passiert rein gar nichts.. :)

 

Ich benutze die standard Syntax für Events und die vom Intellisense vorgeschlagenen Typen..

 

Hier mal in kurzform:

using DVBViewerServer;
...
DVBViewerServer.DVBViewer DVBViewer;
...
DVBViewer = (DVBViewerServer.DVBViewer)System.Runtime.InteropServices.Marshal.GetActiveObject("DVBViewerServer.DVBViewer");
...
DVBViewer.Events.OnChannelChange += new IDVBViewerEvents_OnChannelChangeEventHandler(Events_OnChannelChange);
...
void Events_OnChannelChange(int ChannelNr)
{
//diese methode wird einfach nicht ausgeführt
}

 

Gibt es einen speziellen Grund warum bei mir Events_OnChannelChange beim Kanalwechel nicht ausgeführt wird? Was habe ich übersehen?

 

Ich hoffe ihr könnt mich hier in die richtige Richtung schubsen.. :bye:

Link to comment

Hallo nochmal!

 

Soo... Events bekomme ich jetzt... Offenbar gibt's (zumindest bei mir) mit den Events Probleme wenn der DVBViewer mit der Entwicklungsumgebung in einer virtuellen Maschine läuft... Auf einem anderen System klappt es.

 

Allerdings habe ich jetzt ein weiteres, "winzig kleines" Problem...

Ich hole mir ja mit

DVBViewer = (DVBViewerServer.DVBViewer)System.Runtime.InteropServices.Marshal.GetActiveObject("DVBViewerServer.DVBViewer");

das COM Object... aber nach einer Weile (ich empfange Events - alles ist gut) beenden sich laut VSDebug-Ausgabe zwei Threads und dann kommen keine Events mehr.. will ich dann die Events nochmal eintragen (ja.. soll man im echten Leben nicht.. :bye: ) dann meint das System eine Exception zu werfen weil das COM Object ja gar nicht mehr da ist... Als wenn es von dem GC gelöscht wurde, aber ich hatte ja noch Verweise darauf (DVBViewer wird erst zum Ende der App genullt..)...

 

Gibt es da schon Erfahrungswerte? benutzen tue ich den DVBViewer 3.5.0

 

Grüße...!

Edited by tausi
Link to comment

Ich kenne jetzt Deinen ganzen Code nicht, aber vielleicht hilft Dir die Falle, in die ich schon ein paar mal gestolpert bin:

 

ICOMInterface ###### = <Erzeuge COM Objekt>;
ICOMAnderesInterface yyy = ######.ErzeugeWasWeissIch();

 

Im Folgenden wird dann nur noch mit yyy gearbeitet, ###### ruht vor sich hin. Der Gag ist, dass .NET nach dem obigen Code jederzeit (!) berechtig ist, ###### freizugeben, da es ja nicht mehr verwendet wird. Von einer COM Abhängigkeit zwischen ###### und yyy weiß das Framework natürlich nix - und die muß ja auch nicht vorhanden sein. War es aber bei mir: ###### ist eine Art Datenbankverbindung und yyy eine Art aktiver Suche. Wenn aber ###### freigegeben wird, wird yyy ungültig. Das passiert mal und mal nicht, mal früher, mal später.

 

Das ist der offizielle Ausweg:

 

GC.KeepAlive(######);

 

Jochen

Link to comment
  • 3 weeks later...
Das ist der offizielle Ausweg:

 

GC.KeepAlive(######);

 

Soo.. bin jetzt wieder dazu gekommen das ganze mal wieder mit den Events auszuprobieren.. hatte es seit dem Problem über polling gelöst...

 

Leider bringt mir das GC.KeepAlive keine Erleichterung, da es nur bis zum Ende der Methode greift, ich das Objekt aber in einer Steuer-Klasse habe...:

 

Hier auf das notwendigste gekürzt:

public class DVBVconnector
{
DVBViewerServer.DVBViewer DVBViewer;
System.Timers.Timer checkDVBV;
bool verbunden;
bool hooked;
//....

public DVBVconnector()
{
	checkDVBV = new System.Timers.Timer(1000);
	checkDVBV.Elapsed += new ElapsedEventHandler(checkDVBV_Elapsed);
	//...
}

public void DVBVconnect()
{
	if (!connect())
	{
		//Timer zum regelmäßigen connect() starten..
		checkDVBV.Start();
	}
	else
	{
		hookUp();
	}
}

public void DVBVdisconnect()
{
	checkDVBV.Stop();
	unHook();
	DVBViewer = null;
	verbunden = false;
}

private bool connect()
{
	if (!verbunden)
	{
		try
		{
			DVBViewer = (DVBViewerServer.DVBViewer)System.Runtime.InteropServices.Marshal.GetActiveObject("DVBViewerServer.DVBViewer");
			verbunden = true;
			connect_counter = 0;
			//...
		}
		catch (SystemException)
		{
			verbunden = false;
			if (connect_counter++ > connect_countermax)
			{
				checkDVBV.Enabled = false;
				DVBViewer = null;
				verbunden = false;
			}
			//...
		}
		GC.KeepAlive(DVBViewer);
	}
	return verbunden;
}

void checkDVBV_Elapsed(object sender, ElapsedEventArgs e)
{
	checkDVBV.Enabled = false;
	if (!verbunden)
	{
		if (connect())
		{
			hookUp();
		}
	}

	if (connect_counter < connect_countermax)
	{
		checkDVBV.Enabled = true;
	}
}

private void hookUp()
{
	if (verbunden && !hooked)
	{
		try
		{
			DVBViewer.Events.OnChannelChange += new IDVBViewerEvents_OnChannelChangeEventHandler(Events_OnChannelChange);
			hooked = true;
		}
		catch (SystemException ex)
		{
			Debug.WriteLine("hookUp.. ");
			Debug.WriteLine(ex.Message);
		}
	}
}

private void unHook()
{
	if (verbunden && hooked)
	{
		try
		{
			DVBViewer.Events.OnChannelChange -= Events_OnChannelChange;
			hooked = false;
		}
		catch (SystemException ex)
		{
			Debug.WriteLine("unHook.. ");
			Debug.WriteLine(ex.Message);
		}
	}
}

public void Events_OnChannelChange(int ChannelNr)
{
	Debug.WriteLine("onChannelChange");
	if (connect())
	{
		try
		{
			Debug.WriteLine("Aktueller Kanal: " + ChannelNr.ToString());
			//... (noch Sachen mit DVBViewer)
		}
		catch (SystemException ex)
		{
			verbunden = false;
			Debug.WriteLine("Events_OnChannelChange..");
			Debug.WriteLine(ex.Message);
		}
	}
}
}

 

In meiner Anwendung gibt's dann ein:

  //Initialisierung
dvb = new DVBVconnector();

 //Connect Button gedrückt
dvb.DVBVconnect();

 //Disconnect Button gedrückt
dvb.DVBVdisconnect();

 

Tja... und nachdem er dann ein paar Minuten lang Events bekommt.. hört's dann einfach auf... und das GC.KeepAlive kann ich da nicht wirklich irgendwo einsetzen, oder? Denn ich erstelle und benutze das DVBViewer Objekt ja nicht nur in einer Methode.. sondern in der ganzen Klasse...

 

So.. das erstmal als Update... :)

Link to comment

Korrekt: KeepAlive() ist nur ein Goody, wenn man in einer Methode arbeitet. Also bei Dir: ab in die Tonne!

 

Ok, ich kann jetzt auf die Schnelle nicht alles nachvollziehen (sorry, wenn das so eh nicht passen würde), aber folgender Hinweis: wenn man ein COM Objekt erzeugt, muß man es 'ordentlich' freigeben. Ein = null bewirkt nur, dass die eigentliche COM Freigabe irgendwann während der GC passiert und das hat dann eigenartige Effekt fern ab des eigentlichen Problems zur Folge.

 

Beispiel: statt

 

DVBViewer = null;

 

using System.Runtime.InteropServices;
...
if (DVBViewer != null)
{
 Marshal.ReleaseComObject(DVBViewer);
 DVBViewer = null;
}

 

Sollte aber in Deinem Fall nichts machen, wenn Du nicht Connect/Disconnect drückst, oder? Wenn es daran liegen sollte: das gilt natürlich auch für Sekundärobjekte, die Du vom COM Objekt erhälts (Events mal außen vor, ich vermute, das ist intern geregelt).

 

Beispiel:

IIrgendeineSchnittstelle irgendwas = DVBViewer.GibMirIrgendWas();
try
{
 ...
}
finally
{
 if ((irgendwas != null) && Marshal.IsComObject(irgendwas)) Marshal.ReleaseComObject(irgendwas);
}

 

Vielleicht hilft's oder gibt zumindest Anstoß zum Suchen.

 

So long

 

Jochen

Link to comment
Korrekt: KeepAlive() ist nur ein Goody, wenn man in einer Methode arbeitet. Also bei Dir: ab in die Tonne!

 

Ok, ich kann jetzt auf die Schnelle nicht alles nachvollziehen (sorry, wenn das so eh nicht passen würde), aber folgender Hinweis: wenn man ein COM Objekt erzeugt, muß man es 'ordentlich' freigeben. Ein = null bewirkt nur, dass die eigentliche COM Freigabe irgendwann während der GC passiert und das hat dann eigenartige Effekt fern ab des eigentlichen Problems zur Folge.

 

Hmmm... macht Sinn... ;) Das werd ich gleich mal ändern.. Des saubereren Codes wegen - denn an dem Problem an sich wird sich wohl nix ändern, weil ich das COM Object ja auch eigentlich gar nicht loswerden will.. ;) Es sei denn DVBViewer ist aus..

 

Danke für den Hinweis..

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...