Długa odpowiedź brzmi: zależy to od wielu rzeczy. Krótka odpowiedź brzmi: tak. Tak tak.
Zróbmy eksperyment i zobaczmy najczęstszą sytuację domyślną. Mamy dwie aplikacje konsolowe i jedną wspólną bibliotekę klas, która jest polecana przez obie aplikacje konsolowe. Pierwsza aplikacja konsolowa pełni rolę klienta, a druga ma rolę serwera.
pierwsze, oto co powszechnie zależało biblioteka klasa zawiera:
public interface IFactory {
string Hello(string name);
}
Teraz jakiegoś kodu serwera. Oto uruchomić:
private static TcpChannel channel;
static void Main(string[] args) {
BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();
BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = TypeFilterLevel.Full;
channel = new TcpChannel(
properties: new Hashtable {
{ @"port", 2013 }
},
clientSinkProvider: clientProv,
serverSinkProvider: serverProv
);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Factory), "Factory.rem", WellKnownObjectMode.SingleCall);
Console.WriteLine("Server started...");
Console.WriteLine("Press any key to stop...");
Console.ReadKey(intercept: true);
}
Właśnie wymienione klasy o nazwie Fabryka.
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Factory), "Factory.rem", WellKnownObjectMode.SingleCall);
Zgadłeś. To IFactory realizacja:
private sealed class Factory : MarshalByRefObject, IFactory {
#region IFactory Members
string IFactory.Hello(string name) {
return @"Hello " + name + @" !";
}
#endregion
}
Teraz jakiegoś klienta:
static void Main(string[] args) {
Console.WriteLine("Press any key to connect...");
Console.ReadKey(intercept: true);
IFactory factory = Activator.GetObject(typeof(IFactory), @"tcp://127.0.0.1:2013/Factory.rem") as IFactory;
EventWaitHandle signal = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset);
ThreadStart action =() => {
signal.WaitOne();
var result = factory.Hello("Eduard");
Console.WriteLine(result);
};
foreach (var i in Enumerable.Range(0, 99))
new Thread(action) { IsBackground = true }.Start();
Console.WriteLine("Press any key to bombard server...");
Console.ReadKey(intercept: true);
signal.Set();
Console.ReadKey(intercept: true);
}
Wiesz już wszystko z tych rzeczy, jestem pewien. Otrzymujemy przezroczyste proxy do usługi SingleCall po drugiej stronie (obaj są na tym samym komputerze, a my za pomocą portu TCP 2013):
IFactory factory = Activator.GetObject(typeof(IFactory), @"tcp://127.0.0.1:2013/Factory.rem") as IFactory;
Następnie dla „symultaniczne-Ness” powodów tworzymy 100 wątków, zacznij je (co może zająć trochę czasu), ale „trzymać je na smyczy” (sygnał jest podstawowym środkiem synchronizacji OS), dopóki nie „ciągnąć za spust”:
EventWaitHandle signal = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset);
ThreadStart action =() => {
signal.WaitOne();
var result = factory.Hello("Eduard");
Console.WriteLine(result);
};
foreach (var i in Enumerable.Range(0, 99))
new Thread(action) { IsBackground = true }.Start();
Tak chociaż wszystkie 100 wątków zostały utworzone i rozpoczęte, wszystkie czekają w następującej inwokacji:
signal.WaitOne();
W ten sposób możemy uzyskać, aby rozpocząć w tym samym czasie lepiej, w przeciwnym wypadku stworzenie i uruchomienie wątków będzie sama dokonały ich faktyczne wykonanie bardziej lub mniej sekwencyjną.
Pytamy użytkownikowi zdecydować, kiedy „bombardować serwer” 100 Witam inwokacji:
Console.WriteLine("Press any key to bombard server...");
Console.ReadKey(intercept: true);
signal.Set();
i to, co się dzieje:
1) Zaczynamy aplikację konsoli serwera i uruchomić ją w spokoju:
![enter image description here](https://i.stack.imgur.com/pF3hW.jpg)
2) Rozpoczynamy klient app konsoli „nawiązać połączenie” przez naciśnięcie dowolnego klawisza (który jest tylko połączenie logiczne, ponieważ to właśnie tworzy przezroczyste proxy), ale odroczyć „bombardowanie”:
![enter image description here](https://i.stack.imgur.com/PtPik.jpg)
3) My uruchomić Mark Russinovichem na Process Explorer i użyć go do odkryć klienta proces w liście procesów, a robiąc to możemy otworzyć to okno właściwości i wybrać zakładkę TCP/IP:
![enter image description here](https://i.stack.imgur.com/u51wS.jpg)
4) Udało nam się trafić dowolny klucz w aplikacji klienta i .. TA DAA !! Otrzymujesz dużo połączeń w Process Explorer. Czy oni sto? Czasem tak, czasem nie. To jest pula połączeń, to na pewno. Po krótkiej chwili (5 do 10 sekund) bezczynności zostają one zamknięte, co jest bardzo dobrą rzeczą (ponieważ stos .NET Remoting jest zaimplementowany w ten sposób).
![enter image description here](https://i.stack.imgur.com/CJEEy.jpg)
Mam nadzieję, że ten eksperyment ogólnie odpowiedział na to pytanie.
W bardziej konkretnych przypadkach iw bardziej rygorystycznym sensie powinieneś zapoznać się z dokumentacją i przeczytać o różnych kanałach, które możesz wykorzystać w swoich aplikacjach .NET Remoting (jest ich mnóstwo, co widziałeś tutaj jest tylko zwykły TcpChannel oficjalnie dostarczony przez Microsoft, to zależy od tego, co mówi konfiguracja .NET Remoting, od tego, czy hostujesz serwer w IIS, czy nie, itd.).
Myślę, że to zależy od tego, z jakiego kanału (kanałów) są używane, ale * dlaczego * piszesz remoting code w 2013? –
@Damien_The_Unbeliever może pracował nad starym projektem. co masz na myśli, że zależy to od kanału? kanały to określają? – m1o2