-
На сервере создается и маршализируется некий объект:
...
RemoteObject ro =
new RemoteObject (SomeParam);
RemotingServices.SetObjectUriForMarshal(ro,"bla-bla");
RemotingServices.Marshal(ro);
Понятное дело, что объект по истечении определенного времени (5 мин) убивается сборщиком мусора. Чтобы не допустить этого, сделал следующее.
class LifeTimeSponsor: ISponsor
}
Ну, и после маршализации удаленного объекта сделал следующее:
ISponsor sponsor = new LifeTimeSponsor();
ILease lifetime = (ILease)si.GetLifetimeService();
lifetime.Register(sponsor);
Это, кажется, работает, т.е, объект на сервере не убивается сборщиком до завершения приложения. Но, в связи с тем, что приведенное решение является плодом собственных изысканий в новой для меня среде, есть вопросы такого плана к коллегам, имеющим опыт работы с .Net: 1. Стандартен ли такой подход? 2. Нет ли каких подводных камней, которые я упустил? 3. Есть ли альтернативные (более простые) подходы. 4. Ну, и не накосячил ли я где? ;) Спасибо.
-
Сорри, вот это ILease lifetime = (ILease)si.GetLifetimeService(); читать как ILease lifetime = (ILease)ro.GetLifetimeService(); Просто опечатка.
-
А GC.KeepAlive не спасет отца русской демократии?
-
>>ИА (16.01.06 07:13) [2]
Не спасёт.
>>Джо © (16.01.06 05:15)
См. в MSDN: Activation of Remote Objects (в индексе "client-activated objects" либо "server-activated objects"). В 2005-м ссылка такая: ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_fxremoting/html/e90d0c64-00da-4080-ae78-a6c558825c25.h tm
-
-
> [4] Курдль © (16.01.06 10:39)
Спасибо, поищу. Кажется, была где-то в эл. виде, буду потихоньку читать. ---- > [3] Lamer@fools.ua © (16.01.06 09:59)
Спасибо. Попробовал воспользоватьсе этим способом из указанного топика: You can create the former type of Singleton object by overriding the InitializeLifetimeService method of MarshalByRefObject to return a null reference (Nothing in Visual Basic). This effectively keeps the object in memory as long as the host application domain is running. Переопределил у remote class указанный метод, чтобы он возвращал null, однако, не смотря на это, объект убивается на сервере спустя некоторое время, как и прежде. Или я что-то упустил? Да, я не привел код клиента, ссылку на object proxy получаю так:
RemoteObject ro =
(RemoteObject)Activator.GetObject(
typeof(RemoteObject),
connection_string
);
-
И еще одно. Я не использую RemotingConfiguration.RegisterWellKnownServiceType так в моем случае не хотелось бы использовать конструктор по умолчанию, вызываемый в данном случае.
-
В общем, пока нарисовался такой вариант (несколько более громоздкий сравнительно с первоначальным).
class LifeTimeSponsor: ISponsor
}
public class RemoteObject: MarshalByRefObject
}
Marshalling и активация на клиенте остались прежними. Регистрацию спонсора переделал так:
ISponsor sponsor = new LifeTimeSponsor();
ILease lifetime = (ILease) RemotingServices.GetLifetimeService(si); lifetime.Register(sponsor);
Вроде бы все работает как нужно, однако не уверен, потому, что мой первоначальный вариант без перекрытия InitializeLifetimeService тоже, кажись, работал. Коллеги, покритикуйте, плиз.
-
В общем, как я убедился, без перекрытия InitializeLifetimeService все тоже прекрасно работает :)
-
Читайте книжки - пользы больше. Но на всяк случай приведу свою тестовую прогу:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Lifetime;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace CommonNameSpace
\tСпонсор аренды продлил аренду.", DateTime.Now);
return TimeSpan.FromSeconds(15);
}
RemoteObject FRemoteObject;
public frmClientMain()
\tЗапущено клиентское приложение.", DateTime.Now);
try
\tСоздан двоичный форматировщик приемника", DateTime.Now);
IDictionary props = new Hashtable();
props["name"] = "MyTcpChannel";
props["port"] = "0";
TcpChannel channel = new TcpChannel(props, null, bsfsp);
ChannelServices.RegisterChannel(channel);
richTextBox1.Text += String.Format("\r\n\tСоздан и зарегистрирован канал", DateTime.Now);
RemotingConfiguration.RegisterActivatedClientType(typeof(RemoteObject), "tcp:
RemoteObject _ro = new RemoteObject(System.Guid.NewGuid().ToString());
if (_ro != null)
\tСоздан удаленный объект.", DateTime.Now);
/*
ClientSponsor _cs = new ClientSponsor(TimeSpan.FromSeconds(10));
_cs.Register(_ro);
*/
ILease lease = (ILease)RemotingServices.GetLifetimeService(_ro);
if (lease != null)
\tЗарегистрирован спонсор аренды.", DateTime.Now);
}
else
MessageBox.Show("Сервис времени жизни не получен", "Ошибка");
}
else
MessageBox.Show("Удаленный объект не получен", "Ошибка");
}
catch(Exception er)
}
public void Unregister(MarshalByRefObject obj)
catch
}
protected override void Dispose( bool disposing )
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
#endregion
[STAThread]
static void Main()
private void button1_Click(object sender, System.EventArgs e)
\tOK!", DateTime.Now);
}
catch(Exception er)
}
private void button2_Click(object sender, System.EventArgs e)
\tПолучено время от сервера: ", DateTime.Now, FRemoteObject.GetCurrentDateTime().ToString());
}
private void frmClientMain_Closed(object sender, System.EventArgs e)
}
}
-
> [9] Курдль © (17.01.06 10:42)
Спасибо, но, как я понял, в общем, это тоже самое, что у меня. Отличие только в том, что спонсор у вас создается на клиенте, а у меня на сервере. Или еще есть какие-то принципиальные отличия?
-
> спонсор у вас создается на клиенте, а у меня на сервере
А кому нужен спонсор на сервере??? 8-()
В том-то и прелесть КАО, что они порождаются на сервере для каждого клиента индивидуально. Их методы могут принимать параметры от "своего" клиента, хранить индивидуальные данные "своего" клиента и т.п. Они умирают, как только перестают быть нужными "своему" клиенту.
Кому нужны неубиваемые КАО? Тогда проще работать с Wellknown objects.
-
> [11] Курдль © (17.01.06 16:13) > А кому нужен спонсор на сервере??? 8-() > В том-то и прелесть КАО,
В том-то и дело, что мне НЕ нужен CAO. У меня SAO. :^)
-
> В том-то и дело, что мне НЕ нужен CAO. У меня SAO. :^)
А тогда зачем ему спонсор аренды??!! :-) Он активируется в памяти всякий раз, как кто-либо обращается к его члену. Точнее, вызывает его метод. Не понимаю, какой смысл продлевать ему жизнь? Ведь он не способен нести никакой полезной информации и не имеет корректного способа "личной идентификации". Т.е. после того, как отработал вызванный метод, SAO превращается в натуральный мусор только и ожидающий уборки. Или я не понял истинных целей? :-)
-
Кстати, Ваш способ инициализации SAO не попадает под его классическое определение, которое предполагает лишь регистрацию, как указано в [6]. Скорее этот способ можно назвать "мануальной маршаллизацией", в которой я не силен :) Но повторюсь, была бы мне известна конечная цель, возможно и мои знания бы пригодились.
-
> [13] Курдль © (17.01.06 17:05) > А тогда зачем ему спонсор аренды??!! :-) > Он активируется в памяти всякий раз, как кто-либо обращается > к его члену.
Ну да, именно так все и происходит. Объект этот создается на сервере один раз, все клиенты, подключающиеся к нему, получают ссылку на один и тот же экземпляр. Фактическая активация происходит при вызове одного из методов, точнее, метода Login серверного объекта.
Только дело том, что если к нему в течение некоторого времени не обращаются, сборщик его убивает. А он должен жить на сервере всегда, ожидая запросов со стороны клиентов. Затем и спонсор аренды, чтобы продлевал ему жизнь неограниченно. Добился этого простой регистрацией спонсора аренды на сервере, который в методе Renewal продлевает жизнь объекта еще на какое-то время.
Может, у меня какая-то путаница?
Если это важно, то суть моего тестового сервера такова. Он реализует работу файлового сервера. Клиенты, подключаясь к экземпляру на сервере, вызывают его методы для листинга директорий и загрузки файлов. В зависимости, он прав подключающегося клиента (они хранятся на сервере), сервер разрешает или нет вызовы определенных методов. Вот и все. В этой схеме меня все устраивает, вопрос был только в методах продления жизни.
-
> В зависимости, он прав
В зависимости от прав. Сорри.
-
Hello alexmoon, > Может, у меня какая-то путаница?
Вроде все логично. Подозрительным кажется только " Фактическая активация происходит при вызове одного из методов, точнее, метода Login серверного объекта.Я думаю, что фактическая активация происходит после вызова конструктора на RemoteObject ro = new RemoteObject
(SomeParam); Еще я опасаюсь, что при определенном количестве методов, объект станет слишком громоздким для постоянно активного состояния на сервере. В моих вариантах используется множество классических SAO (они для удобства проектируются по сущностям, например для работы с субъектами - один, для работы с документами - другой, и т.д.). Все "индивидуальные" данные о клиенте ходят между клиентом и SAO посредством контекста вызова (Call Context). -- Best regards, Logic mailto:Alexmoon@logexp.ru
-
> [17] Курдль © (18.01.06 09:47)
Спасибо за ответ! Вроде со своим примером разобрался. Буду дальше читать литературу.
|