|
|
|
start date: Sat, 11 Aug 2007 00:07:31 +0800,
posted on: microsoft.public.dotnet.framework.remoting
back
| Thread Index |
|
1
terence
|
|
2
Jayme.Pechan
|
why my chatroom can run only once?(about Remoting Event)
Dear All:
At first, sorry for my poor english. I have a chatroom application. it
have three projects: (if you don't want to see my poor code, you man
download the attach file.)
Project 1: MsgBoardShard (Class Library)
Project 2: MsgBrdServer ( Console application, Chat server)
Project 3: MsgBoardClient ( console application, chart client)
i want send some message to server. in the first time, they're all ok, but
if I close the client (Only client) and run it again. when i type any
message, the server side will occor a error : cannot connect to remote
server
three days gone, I'm almost crazy... Any help will be appreciate!!!
=====================================================================
There is a class named "MsgMsgBoard" in project 1:
public delegate void EventDelegate(string info);
[Serializable]
public class MsgBoard : MarshalByRefObject
{
public event EventDelegate OnInfoAdded;
public void AddMessage(string info)
{
Console.WriteLine("SERVER:{0}" , info);
if (OnInfoAdded != null)
OnInfoAdded(info); // error here: cannot connect to remote
server
}
}
and the other one:
[Serializable]
public class EventClass : MarshalByRefObject
{
private EventClass()
{
}
public static EventClass Instance = EventClass.CreateInstance();
public static EventClass CreateInstance()
{
if (Instance == null)
{
Instance = new EventClass();
}
return Instance;
}
public event EventDelegate OnInfoAdded;
public void msgbd_OnInfoAdded(string info)
{
//Console.WriteLine("info from server event:{0}", info);
if (OnInfoAdded != null)
OnInfoAdded(info);
}
}
=====================================================================
In project 2 "MsgBrdServer", i used the config file to publish remoting
service;
static void Main(string[] args)
{
RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
false);
Console.WriteLine("Server...");
Console.ReadLine();
}
----------------------
and the content of the config file :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<customErrors mode="off"/>
<application>
<service >
<wellknown mode="Singleton" type="MsgBoardShard.MsgBoard,
MsgBoardShard" objectUri="MsgBoard" />
</service>
<channels>
<channel ref="http" port="8080">
<serverProviders>
<formatter ref="soap" typeFilterLevel="Full"/>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
=====================================================================
In Project 3, config file:
<?xml version="1.0"?>
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown type="MsgBoardShard.MsgBoard, MsgBoardShard"
url="http://localhost:8080/MsgBoard"/>
</client>
<channels>
<channel ref="http" port="0">
<serverProviders>
<formatter ref="soap" typeFilterLevel="Full"/>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
-----------------------
the program.cs
static void Main(string[] args)
{
RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
false);
EventClass cl = EventClass.Instance;
MsgBoard md = new MsgBoard();
md.OnInfoAdded += new EventDelegate(cl.msgbd_OnInfoAdded);
Console.Title = "MsgBdClient";
string Ss = "";
while (Ss!="q")
{
Ss = Console.ReadLine();
md.AddMessage(Ss);
}
Console.ReadLine();
}
Date:Sat, 11 Aug 2007 00:07:31 +0800
Author:
|
Re: why my chatroom can run only once?(about Remoting Event)
You connect from the client to a singleton object (only 1 ever exists on the
server). Then you add a delegate to the sink chain. The first client is
first in the list on the sink chain. Then you close the client but you
aren't removing the entry from the sink chain on the server. So when the
next client connects and adds itself to the sink chain, it becomes #2 in the
list. Now when an event fires, it calls the delegates in order starting
with the first one. In this case, however, your object no longer exists on
the original computer so it throws the exception. It never gets to the
second one so your new clients event never fires.
There are two things that I do to rectify this. For starters, in the
FormClosing event on your client application, us the -= syntax to remove the
delegate from the servers sink change...
Example: myobj.MyEvent -= myStoredDelegate;
This works great as long as your application closes nicely. But what if you
have clients chatting and someone loses power. Well, it never removes
itself from the sink chain so the server just fails with this exception
you've been getting. To fix this, I change the event implementation on the
server to handle the sink chain myself (there are many ways to do this. My
example is just 1 way to do it.)
Example:
protected List<MyEventDelegate> EventDelegates = new
List<MyEventDelegate>();
public event MyEventDelegate MyEvent
{
add
{
lock (EventDelegates)
EventDelegates.Add(value);
}
remove
{
lock (EventDelegates)
EventDelegates.Remove(value);
}
}
protected void FireMyEvent()
{
MyEventDelegate[] tAry;
lock (EventDelegates)
tAry = EventDelegates.ToArray();
foreach (EventDelegate t in tAry)
{
try
{
t();
}
catch // you will want to handle the exceptions that
make sense to you here.
{
MyEvent -= t; // remove this entry from the sink
chain so it doesn't get called in the future.
}
}
}
With this code you can hook up the events the same way you always do:
myObject.MyEvent += new MyEventDelegate(MyEventFunction);
There are areas where you can improve on this but this is the idea.
Hope this helps.
Jayme
Date:Tue, 14 Aug 2007 14:39:16 -0700
Author:
|
|
|