【问题标题】:c# remote eventsc# 远程事件
【发布时间】:2011-03-17 04:58:30
【问题描述】:

我正在尝试做一个服务器客户端应用程序,以了解有关使用 c# 的远程程序的更多信息。

结构很简单。

我有一个服务器,它在调用函数 updateInventory 并且每个客户端向事件注册一个函数(使用委托)时触发一个事件。

因此,当任何客户端更新库存(通过调用 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;
    }

}

库存管理器

其中声明了委托、事件以及何时触发事件的状态。客户端具有相同的类,唯一的区别是 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>

如果有人能给我一些帮助,我将不胜感激。 提前致谢

【问题讨论】:

  • 在开始使用 .NET Remoting 之前,您应该阅读 documentation 明确指出它是并且已废弃的技术:“不建议用于新开发。”。
  • c# remote events 的完全相同的副本

标签: c# .net-remoting


【解决方案1】:

我想您的问题是,您没有看到该事件正在引发?我的意思是:事件处理程序(在您的情况下是 Warn 方法)没有执行?

原因是您不能在一个 AppDomain 上调用这样的事件,并假设您可以在另一个 AppDomain 中处理该事件。 为了能够做到这一点,您还需要某种“代理”对象,即MarshalByRef'ed。

例如,该类可能如下所示:

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

【讨论】:

    猜你喜欢
    • 2012-09-27
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多