.NET Remoting. Remote Events
От: Caezar  
Дата: 19.02.06 21:11
Оценка:
Никто не сталкивался с такой ситуацией? :

Клиент подписывается на ремоутные ивенты от сервера.
Всё нормально работает, но после некоторого времени не проходит вызов клиентского метода, определённого делегатом для обработки этого ивента.
На серверной стороне никаких эксепшенов.
Может тут GC как-то виноват? //предположение

"генерация" ивента происходит следующим образом (делал как написано в книже Microsoft .NET Remoting)

private    void    NotifyClients(GoodEventArgs args)
{
    Console.WriteLine("NotifyClients called");
    System.Delegate[] invkList = GoodEvent.GetInvocationList();
    IEnumerator ie = invkList.GetEnumerator();
    while(ie.MoveNext())
    {
        GoodEventHandler handler = (GoodEventHandler)ie.Current;
        try
        {
            Console.WriteLine("\tInvoking " + ie.Current.ToString());
            IAsyncResult ar = handler.BeginInvoke(this, args, null, null);
        }

        catch(System.Exception e)
        {
            Console.WriteLine("EXCEPTION: " + e.Message);
            GoodEvent -= handler;
        }
        Console.WriteLine("\tSuccessfully invoked " + ie.Current.ToString());
    }
}
Re: .NET Remoting. Remote Events
От: Cypress  
Дата: 19.02.06 21:29
Оценка:
Здравствуйте, Caezar, Вы писали:

C>Skip


Дело может быть в том, что если подписчиков много, и сервер начинает их дергать,
а в середине списка оказывается делегат на клиента который отключился, дальше дерганье делегатов не проходит!

Выход прост, надо брать список подписчиков, и дергать всех по очереди!
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: .NET Remoting. Remote Events
От: Caezar  
Дата: 19.02.06 21:41
Оценка:
Здравствуйте, Cypress, Вы писали:

C>Здравствуйте, Caezar, Вы писали:


C>>Skip


C>Дело может быть в том, что если подписчиков много, и сервер начинает их дергать,

C>а в середине списка оказывается делегат на клиента который отключился, дальше дерганье делегатов не проходит!

C>Выход прост, надо брать список подписчиков, и дергать всех по очереди!


Ув. Cypress, если вы посмотрите на код, то именно так я и делаю.
Кроме того клиенты не отключаются. Это происходит при running clients.
Такое происходит при любом кол-ве клиентов. (любое <= 15)
Re: .NET Remoting. Remote Events
От: Speedman Украина http://shvydky.blogspot.com
Дата: 19.02.06 21:51
Оценка: 2 (1)
Здравствуйте, Caezar, Вы писали:

C>Никто не сталкивался с такой ситуацией? :


C>Клиент подписывается на ремоутные ивенты от сервера.

C>Всё нормально работает, но после некоторого времени не проходит вызов клиентского метода, определённого делегатом для обработки этого ивента.
C>На серверной стороне никаких эксепшенов.
C>Может тут GC как-то виноват? //предположение

При такой модели, у тебя клиент и сервер по-сути поменялись местами в том месте где событие. Это означает что для клиента надо учитывать весь тот геморрой что и для сервера, включая время жизни объекта — подписчика событий (потому что именно он теперь сервер). Смотреть надо в сторону LifetimeServices.

--
Андрей
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Andrey Shvydky
http://shvydky.blogspot.com
.NET Remoting. Remote Events
От: Аноним  
Дата: 19.02.06 21:52
Оценка:
InitializeLifetimeService клиента возвращает null?


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re: .NET Remoting. Remote Events
От: DreamSonic  
Дата: 19.02.06 22:25
Оценка:
Здравствуйте, Caezar, Вы писали:

C>Никто не сталкивался с такой ситуацией? :

C>Клиент подписывается на ремоутные ивенты от сервера.
C>Всё нормально работает, но после некоторого времени не проходит вызов клиентского метода, определённого делегатом для обработки этого ивента.
C>На серверной стороне никаких эксепшенов.
C>Может тут GC как-то виноват? //предположение
C>"генерация" ивента происходит следующим образом (делал как написано в книже Microsoft .NET Remoting)

Если имеешь дело с ремоутингом, прежде всего нужно удостовериться, что клиент всё ещё жив. Не истекло ли время жизни? Есть ли спонсор? Не умер ли сам спонсор?
Вообще в этом случае должен быть RemotingException, но т.к. вызов асинхронный, я понимаю, что он как-то проходит мимо. Предлагаю для проверки этой теории вызывать события явно.
Re: .NET Remoting. Remote Events
От: Caezar  
Дата: 20.02.06 12:39
Оценка:
Господа, всем большое спасибо за советы.
Действительно это было связано с lease lifetime.

Полечилось

<lifetime 
    leaseTime="0"
    renewOnCallTime="0" 
/>


в .config -e клиента
Re: .NET Remoting. Remote Events
От: arh Россия  
Дата: 21.02.06 13:59
Оценка:
Здравствуйте, Caezar, Вы писали:

C>На серверной стороне никаких эксепшенов.


Эти исключения надо получать в EndInvoke
... << RSDN@Home 1.1.4 stable rev. 510>>
Все изложенное является моим личным мнением на текущий момент.
Re[2]: .NET Remoting. Remote Events
От: Caezar  
Дата: 21.02.06 14:51
Оценка:
Здравствуйте, arh, Вы писали:

arh>Здравствуйте, Caezar, Вы писали:


C>>На серверной стороне никаких эксепшенов.


arh>Эти исключения надо получать в EndInvoke


Валидное замечание.
Re[2]: .NET Remoting. Remote Events
От: Аноним  
Дата: 27.10.06 20:11
Оценка:
Здравствуйте, Caezar, Вы писали:

C>Господа, всем большое спасибо за советы.

C>Действительно это было связано с lease lifetime.

C>Полечилось


C>
C><lifetime 
C>    leaseTime="0"
C>    renewOnCallTime="0" 
C>/>

C>


C>в .config -e клиента


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();
        }
    }
}


ведь код практически идентичен коду в книге, что здесь надо испрпавить?
если не затруднит, плиз код обоих конфигов и исправленные листинги
а то совсем голова кругом идёт, и мысли кончаются
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.