【问题标题】:Exposing a winforms application internals through WCF通过 WCF 公开 winforms 应用程序内部
【发布时间】:2012-07-26 13:56:32
【问题描述】:

我正试图在 IPC 和 WCF 中迈出第一步,但到目前为止,我的表现还是差强人意。我有一个 Winforms 应用程序,我想为远程调用者提供一些工具。 winforms 应用程序的大部分业务逻辑都局限于一个处理所有后台工作的单例。我想通过 IPC 机制公开一些功能。 WCF 似乎是前进的方向,所以我从它开始。

我尝试将 WCF 服务库项目添加到我的解决方案中,我想通过它公开一些调用。当我在 VS 调试器中启动 Winforms 项目时,它正常运行,并且 WcfSvcHost 启动。我可以使用 WcfTestClient 与 WCF 服务通信。

但是,当我尝试访问包含我想与之通信的代码的单例时,似乎我得到了一个新的单例对象。显然,我做错了;我猜正在发生的事情是服务在不同的进程中运行,因此没有真正的共享代码,因此没有共享单例。

我不确定我应该如何继续。我选择为 IPC 使用 WCF 是错误的吗?我应该在 Winforms 应用程序中集成 WCF 端点吗?我正在尝试的方法是否可行?

编辑:我认为这太高级了,也太简单了,以至于任何代码示例都毫无用处。我想我错了。所以一些代码:

在 WinForms 程序集中:

public partial class Form1 : Form
{
  public Form1()
    {
      InitializeComponent();
      label1.Text = MySingleton.Instance.InitedAt.ToString();
    }
}

public class MySingleton
{
  private static MySingleton instance = new MySingleton();
  private DateTime inited;

  private MySingleton()
  {
    this.inited = DateTime.Now;
  }

  public static MySingleton Instance
  {
    get
    {
      return instance;
    }
  }

  public DateTime InitedAt
  {
    get
    {
      return this.inited;
    }
  }
}

在 WCFServiceLibrary 程序集中:

[ServiceContract]
public interface IApplicationProbe {

  [OperationContract]
  string DoesItWork();

  [OperationContract]
  string SingletonInited();
}

public class ApplicationProbe : IApplicationProbe {
  public string DoesItWork(){
    return "Why yes, yes it does";
  }

  public string SingletonInited(){
    return MySingleton.Instance.InitedAt.ToString();
  }
}

当我通过 WcfTestClient 查询 SingletonInited 时,我得到了一个与 winforms 单例实例化的 DateTime 不同的 InitedAt。

编辑2:

我让这段代码按原样运行(使用围绕 Winforms 的自动生成的脚手架)。表单上的标签显示的时间与 WCF 调用返回的时间不同,表明它是不同的实例。

【问题讨论】:

  • 带有 WCF 的 IPC 通常使用命名管道完成。它当然受到支持;但是有很多开销。除了 WCF 之外,还有更多执行 IPC 的高性能方法。例如,内存映射文件。
  • 您的意思是 WCF 而不是 WPF?这是第一个设置:首先让它工作,然后让它有效地工作。由于我还不能完成第一步,所以我还没有进入第二步,但我认为 Named Pipes 将是一个不错的候选者。我会查看内存映射文件,感谢您的建议。
  • 是的,WCF,不是 WPF...自动更正 :)
  • 由于这主要不是关于大量数据交换,而是更多关于让另一端的应用程序做一些提升/工作,MMFs 裸机风格似乎不如管理更多/适合我的类型安全 WCF。

标签: c# visual-studio-2010 wcf ipc


【解决方案1】:

我假设您将单例类用作服务(它实现了合同)。我建议你开发一个 WCF 合约和一个服务,它会调用你的单例。

所以你会有这样的东西:

public class YourImpportantSingleton
{
    public YourImpportantSingleton Instance { get; set; }
    public void DoSeriousBusiness(){...}
}

[ServiceContract]
public interface IYourContract
{
    void YourRemoteAction();
} 

public class YourService : IYourContract
{
    public void YourRemoteAction()
    {
        YourImportantSingleton.Instance.DoSeriousBusiness();
    }
}

UPD:好的,刚刚意识到,您可能没有在 winforms 应用程序中使用自托管,很抱歉浪费了时间。

然后,您的选择将是在您的表单应用程序中托管一个带有ServiceHost 的服务,或者单独托管一个服务(例如,使用 IIS)并使该服务成为您的单例的守护者。当然,您必须更改表单应用程序以调用单独的服务,因为它现在保持状态。

【讨论】:

  • 我为我现在拥有的东西添加了一些代码,看起来和你的很像
  • @Martijn,那么 WCF 不会创建您的单例的第二个实例(顺便说一下,您忘记了 static),但它会创建您的服务类的实例。
  • 我忘记了这里的静态参数,只是修复了它们。我将运行我的示例代码,我会让你知道会发生什么。感谢您的关注!
  • 在您的特定示例中,InitedAt 将设置为第一个单例访问时间,因为没有静态构造函数存在 static 字段将被延迟初始化。
  • 我完成了代码并让它运行起来。 (如果您愿意,我可以快速将整个解决方案树放到网上,以便您进行验证)。 WCF 调用显示的时间与表单上的标签显示的时间不同
【解决方案2】:

这里的问题是 WCF 服务主机托管的是服务,而不是应用程序本身。这导致应用程序在单独的 ApplicationDomain 中运行,进而导致创建新的单例。切换到自托管解决了这个问题。

【讨论】:

    猜你喜欢
    • 2021-07-01
    • 2014-03-06
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多