我正在尝试制作一个服务器客户端应用程序来了解有关使用 C# 的远程程序的更多信息。
结构非常简单。
我有一个服务器,当调用函数 updateInventory 时,它会触发一个事件,并且每个客户端都会向该事件注册一个函数(使用委托(delegate))。
因此,当任何客户端更新库存(通过调用 updateInventory 函数)时,所有客户端都会通过事件收到警告。
现在的问题是它根本不起作用,当客户端调用 updateInventory 函数时,服务器中的函数不会被调用。
该程序有以下 4 个组件:
inventoryChangedArgs
它是可序列化的,并作为事件触发的函数的参数。我将其编译为 .dll 并通过“添加引用...”在服务器和客户端上使用:
using System;
[Serializable]
public class InventoryChangeArgs:EventArgs
{
private string pno;
public string Pno
{
get
{
return pno;
}
set
{
pno = value;
}
}
private int change;
public int Change
{
get
{
return change;
}
set
{
change = value;
}
}
public InventoryChangeArgs(string pno, int change)
{
Console.WriteLine("InventoryChangeArgs constructed");
this.pno = pno;
this.change = change;
}
}
库存管理器
其中声明委托(delegate)、事件并说明何时触发事件。客户端具有相同的类,唯一的区别是 UpdateInventory 内容为 null...其他所有内容都相同。
public class InventoryManager:MarshalByRefObject
{
public delegate string InventoryChangeHandler(object sender, InventoryChangeArgs info);
public event InventoryChangeHandler Changed;
public void UpdateInventory(string pno, int change)
{
Console.WriteLine("UpdateInveroty has been invoced");
if (change == 0)
Console.WriteLine("No changed event");
else if (Changed != null)
{
Changed(this, new InventoryChangeArgs(pno, change));
Console.WriteLine("Changed event");
}
}
}
事件在客户端的功能 向事件添加 Wan 功能并设置远程配置:
class Client
{
static void Warn(object sender,InventoryChangeArgs args)
{
Console.WriteLine("It was changed by: {0] the {1}",args.Change,args.Pno);
}
static void Main(string[] args)
{
RemotingConfiguration.Configure("Client.exe.config",false);
InventoryManager inv=new InventoryManager();
inv.Changed+=new InventoryManager.InventoryChangeHandler(Warn);
Console.WriteLine("Client started");
inv.UpdateInventory("102", 2);
Console.ReadLine();
}
}
远程配置文件 这是客户端的远程配置文件,服务器端几乎相同,除了以下几行:
...
<application name="Server">
<service>
<wellknown
mode="Singleton"
type="InventoryManager, InventoryManager"
objectUri="InventoryManager" />
</service>
...
<channel ref="tcp" port="9000">
...
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown
type="InventoryManager, InventoryManager"
url="tcp://localhost:9000/Server/InventoryManager"
/>
</client>
<channels>
<channel ref="tcp" port="0">
<serverProviders>
<formatter ref="binary" typeFilterLevel="Full" />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
如果有人能给我一些帮助,我将不胜感激。 提前致谢
最佳答案
我想您的问题是,您没有看到正在引发该事件?我的意思是:事件处理程序(您的例子中的 Warn 方法)没有执行?
原因是您无法在一个 AppDomain 上调用此类事件,并且假设您可以在另一个 AppDomain 中处理该事件。
为了能够做到这一点,您还需要某种经过 MarshalByRef
处理的“代理”对象。
该类可以如下所示,例如:
public abstract class InventoryManagerUpdatedDelegateObject : MarshalByRefObject
{
public void InventoryManagerUpdatedCallback( object sender, InventoryChangeArgs e )
{
InventoryManagerUpdatedCallbackCore (sender, e);
}
protected abstract InventoryManagerUpdatedCallbackCore( object sender, InventoryChangeArgs e );
public override object InitializeLifetimeService()
{
return null;
}
}
这个类在服务器端和客户端都应该是已知的。因此,最好将其放入定义 InventoryChangeArgs
类的同一个 DLL 中。
在客户端,您可以创建上述类的实现:
public class ConsoleReporter : InventoryManagerUpdatedDelegateObject
{
protected override InventoryManagerUpdatedCallbackCore( object sender, InventoryChangeArgs e )
{
Console.WriteLine("It was changed by: {0] the {1}",args.Change,args.Pno);
}
}
在客户端,执行以下操作:
class Client
{
static void Warn(object sender,InventoryChangeArgs args)
{
Console.WriteLine("It was changed by: {0] the {1}",args.Change,args.Pno);
}
static void Main(string[] args)
{
RemotingConfiguration.Configure("Client.exe.config",false);
InventoryManager inv=new InventoryManager();
ConsoleReporter reporter = new ConsoleReporter();
inv.Changed += reporter.InventoryManagerUpdatedCallback;
Console.WriteLine("Client started");
inv.UpdateInventory("102", 2);
Console.ReadLine();
}
}
关于时间:2019-03-17 标签:c#remoteevents,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5331088/