Клиент подписывается на ремоутные ивенты от сервера.
Всё нормально работает, но после некоторого времени не проходит вызов клиентского метода, определённого делегатом для обработки этого ивента.
На серверной стороне никаких эксепшенов.
Может тут GC как-то виноват? //предположение
"генерация" ивента происходит следующим образом (делал как написано в книже Microsoft .NET Remoting)
Дело может быть в том, что если подписчиков много, и сервер начинает их дергать,
а в середине списка оказывается делегат на клиента который отключился, дальше дерганье делегатов не проходит!
Выход прост, надо брать список подписчиков, и дергать всех по очереди!
Здравствуйте, Cypress, Вы писали:
C>Здравствуйте, Caezar, Вы писали:
C>>Skip
C>Дело может быть в том, что если подписчиков много, и сервер начинает их дергать, C>а в середине списка оказывается делегат на клиента который отключился, дальше дерганье делегатов не проходит!
C>Выход прост, надо брать список подписчиков, и дергать всех по очереди!
Ув. Cypress, если вы посмотрите на код, то именно так я и делаю.
Кроме того клиенты не отключаются. Это происходит при running clients.
Такое происходит при любом кол-ве клиентов. (любое <= 15)
Здравствуйте, Caezar, Вы писали:
C>Никто не сталкивался с такой ситуацией? :
C>Клиент подписывается на ремоутные ивенты от сервера. C>Всё нормально работает, но после некоторого времени не проходит вызов клиентского метода, определённого делегатом для обработки этого ивента. C>На серверной стороне никаких эксепшенов. C>Может тут GC как-то виноват? //предположение
При такой модели, у тебя клиент и сервер по-сути поменялись местами в том месте где событие. Это означает что для клиента надо учитывать весь тот геморрой что и для сервера, включая время жизни объекта — подписчика событий (потому что именно он теперь сервер). Смотреть надо в сторону LifetimeServices.
Здравствуйте, Caezar, Вы писали:
C>Никто не сталкивался с такой ситуацией? : C>Клиент подписывается на ремоутные ивенты от сервера. C>Всё нормально работает, но после некоторого времени не проходит вызов клиентского метода, определённого делегатом для обработки этого ивента. C>На серверной стороне никаких эксепшенов. C>Может тут GC как-то виноват? //предположение C>"генерация" ивента происходит следующим образом (делал как написано в книже Microsoft .NET Remoting)
Если имеешь дело с ремоутингом, прежде всего нужно удостовериться, что клиент всё ещё жив. Не истекло ли время жизни? Есть ли спонсор? Не умер ли сам спонсор?
Вообще в этом случае должен быть RemotingException, но т.к. вызов асинхронный, я понимаю, что он как-то проходит мимо. Предлагаю для проверки этой теории вызывать события явно.
Здравствуйте, arh, Вы писали:
arh>Здравствуйте, Caezar, Вы писали:
C>>На серверной стороне никаких эксепшенов.
arh>Эти исключения надо получать в EndInvoke
Валидное замечание.
Re[2]: .NET Remoting. Remote Events
От:
Аноним
Дата:
27.10.06 20:11
Оценка:
Здравствуйте, Caezar, Вы писали:
C>Господа, всем большое спасибо за советы. C>Действительно это было связано с lease lifetime.
C>Полечилось
C>
remoting недавно стал юзать (так что не злитесь если вопрос покажется глупым ), инструмент Visual Studio 8 Express
у меня таже проблема, только я не понимаю что не так?
вот сервер
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Collections.Specialized;
namespace Server
{
class Program
{
static void Main(string[] args)
{
ListDictionary channelProperties = new ListDictionary();
channelProperties.Add("port", 4000);
BinaryServerFormatterSinkProvider serverSinkProvider = new BinaryServerFormatterSinkProvider();
serverSinkProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
TcpChannel channel = new TcpChannel(channelProperties, null, serverSinkProvider);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Messager), "Messager",
WellKnownObjectMode.Singleton);
Messager msg = new Messager();
ObjRef obj = RemotingServices.Marshal(msg, "TcpService");
Console.WriteLine("Input Enter to exit..");
Console.ReadLine();
}
}
}
вот удалённый объект
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Windows.Forms;
public delegate void MsgEventHandler(string msg);
public interface IServer
{
event MsgEventHandler MsgEvent;
void Notify(string msg);
}
public class Messager : MarshalByRefObject, IServer
{
public event MsgEventHandler MsgEvent;
public override object InitializeLifetimeService()
{
return null;
}
public void Notify(string msg)
{
System.Delegate[] invkList = MsgEvent.GetInvocationList();
IEnumerator ie = invkList.GetEnumerator();
while (ie.MoveNext())
{
MsgEventHandler handler = (MsgEventHandler)ie.Current;
try
{
handler.Invoke(msg);
//может стоит использовать BeginInvoke, только не знаю какие параметры:(
}
catch (Exception e)
{
MsgEvent -= handler;
}
}
}
}
public class MessagerRepeater : MarshalByRefObject
{
public event MsgEventHandler MsgEvent;
public void Handler(string msg)
{
if (MsgEvent != null)
{
MsgEvent(msg);
}
}
public override object InitializeLifetimeService()
{
return null;
}
}
вот клиент
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System;
using System.Collections;
namespace Client
{
class Program
{
public static void MessageReceived(string msg)
{
Console.WriteLine("Принято: "+msg);
}
static void Main(string[] args)
{
Hashtable props = new Hashtable();
props.Add("port", 0);
BinaryServerFormatterSinkProvider serverSinkProvider = new BinaryServerFormatterSinkProvider();
serverSinkProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
TcpChannel channel = new TcpChannel(props, null, serverSinkProvider);
channel.StartListening(0);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownClientType(typeof(Messager), "tcp://localhost:4000/Messager");
IServer m_msg = (IServer)new Messager();
MessagerRepeater m_rep = new MessagerRepeater();
m_msg.MsgEvent+=new MsgEventHandler(m_rep.Handler);
m_rep.MsgEvent += new MsgEventHandler(MessageReceived);
Console.WriteLine("Вдави exit для выхода");
string msg;
do
{
msg = Console.ReadLine();
m_msg.Notify(msg);
}
while (msg != "exit");
Console.ReadLine();
}
}
}
ведь код практически идентичен коду в книге, что здесь надо испрпавить?
если не затруднит, плиз код обоих конфигов и исправленные листинги
а то совсем голова кругом идёт, и мысли кончаются