自托管(WinForm)WCF服务如何与主窗体交互?

Dav*_*vid 2 .net wcf winforms

我想要实现的简化版本:

  • 我有一个WinForms应用程序在后台运行隐藏(Visible = false).
  • 它只有一个Form,我保留了默认名称 - Form1
  • 此WinForms应用程序托管WCF服务.现在我们称之为Listener服务.
  • 此监听器服务具有一个名为"DisplayAlert()"的函数,该函数作为服务函数公开
  • 位于另一台计算机上的应用程序通过标准WCF服务调用向监听器服务发送消息

我已经完成了以上所有工作.我可以在调用DisplayAlert()函数时单步调试代码并观察消息流.

我无法弄明白,我不敢相信如何做到这么简单:

- 我希望托管服务中的DisplayAlert()函数直接与托管它的WinForm交互,以使表单可见.

我想要做的就是将Visibility设置为true,并在WinForm上调用另一个函数.

在我看来,它应该像添加对表单的引用一样简单,或者在表单上创建公共函数并从服务类调用它,但我甚至无法弄清楚如何从服务中引用Form1类.

我错过了一些明显的东西吗 我如何甚至引用托管服务的Form1的实例?

我走了......

  • 在ListenerService(AlertReceived,virtual void OnAlertReceived)中创建一个事件,认为在Form上,我可以添加一个事件处理程序.
    • 没有骰子.我没有直接实例化一个ListenerService类,它正在ServiceHost中运行.
  • 试图从类中引用Application对象,以为我可以将它作为Application.Form1引用,但是nope.我甚至无法在服务类中看到Application对象.
    • 我可能在这里遗漏了一些明显的东西,但我不确定.

还有其他建议吗?

我可以添加代码,如果它有帮助.

Bey*_*ygi 11

使用此方法,您可以完全使用线程安全的应用程序,并且没有任何限制.

服务合同定义

[ServiceContract]
public interface IService
{
    [OperationContract]
    void DisplayAlert();
}
Run Code Online (Sandbox Code Playgroud)

服务实施

public class Service:IService
{
    public void DisplayAlert()
    {
        var form = Form1.CurrentInstance;
        form.MySynchronizationContext.Send(_ => form.Show(), null);
    }
}
Run Code Online (Sandbox Code Playgroud)

Program.cs中

[STAThread]
static void Main()
{        
    var host = new ServiceHost(typeof (Service));
    host.Open();

    Application.SetCompatibleTextRenderingDefault(false);
    Application.EnableVisualStyles();
    Application.Run(new Form1());
 }
Run Code Online (Sandbox Code Playgroud)

表格实施

public partial class Form1 : Form
{
    public static Form1 CurrentInstance;
    public SynchronizationContext MySynchronizationContext;
    private bool showForm = false;

    public Form1()
    {
        InitializeComponent();
        MySynchronizationContext = SynchronizationContext.Current;
        CurrentInstance = this;
    }

    // use this method for hiding and showing if you want this form invisible on start-up
    protected override void SetVisibleCore(bool value)
    {
        base.SetVisibleCore(showForm ? value : showForm);
    }

    public void Show()
    {
        showForm = true;
        Visible = true;   
    }

    public void Hide()
    {
        showForm = true;
        Visible = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

客户

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Press Enter to show form");
        Console.ReadLine();

        var client = new ServiceClient();
        client.DisplayAlert();
    }
}
Run Code Online (Sandbox Code Playgroud)