在服务实现中创建System.Windows.Control时,WCF服务无法正常工作

时间:2018-04-26 14:28:13

标签: c# .net multithreading wcf

我有一个带有服务合同的WCF服务(让我们称之为IHelloWorldService)。在合同实现中(不要问为什么......)构造函数创建一个System.Windows.Control实例。

嗯,使用此配置,该服务根本不起作用。它看起来很完美,但是当我向服务发出请求时(即使我在浏览器中询问元数据),服务也没有响应。 有趣的是,如果我在另一个线程中创建System.Windows.Form(例如在任务内部),该服务可以正常工作。该服务是单例,因此,它不会为每个调用创建新实例。控件创建一次。

我的例子的快速伪代码是:

创建服务主机:

   ServiceHost serviceHost = new ServiceHost(new HelloWorldService(), "callback");

服务:

   class HelloWorldService : IHelloWorldService
   {
       public HelloWorldService() : this(new System.Windows.Control())
       {}

       public HelloWorldService(System.Windows.Control control){}
   }

上一个示例不起作用。但是,如果我在另一个线程中创建HelloWorldService,例如,在Task中,它可以完美地工作。 快速粗伪代码示例:

   ServiceHost serviceHost = new ServiceHost(CreateHelloWorldService(), "callback");

   HelloWorldService CreateHelloWorldService()
   {
       HelloWorldService service;
       Task newTask = new Task{ service = new HelloWorldService() };
       newTask.Run().Wait();
       return service;
   }

此示例效果很好。我的猜测是,当主线程创建控件然后WCF堆栈无法处理请求时,主线程可能会遭受某种更改。这个问题是一个更大的问题的简化,虽然我能够用线程解决它,我想/需要了解发生了什么以及为什么不能正常工作以解释这个大问题在真实环境计划中。

为我的英语道歉。如果有什么不清楚的地方,请告诉我,我会尽力澄清。 提前谢谢!

1 个答案:

答案 0 :(得分:0)

  1. 服务并不意味着创建Windows窗体组件。即使你以某种方式成功实现了创作,稍后也会出现与之交互的问题。

  2. Windows表单控件意味着在后台线程中处理,因为创建它的线程必须与与之交互的线程相同。所有交互都需要使用InvokeRequired,然后在TPL之前的时间执行BeginInvoke。使用TPL,使用交互应该在任务有界操作

  3. 在你的代码片段中,因为正在使用的实际线程在方法调用之后被释放,所以表单将变成一个僵尸,因为没有引用来控制它..(一个可能的未来处理问题的例子服务中的表格)

  4. 代码方面,只要我们使用Invoke / BeginInvoke,就会出现NO问题,如下面的示例所示

    public delegate void myDel();
    
    public class Service1 : MyService
    {
        private WindowsFormsApp1.Form1 form;
    
        public Service1()
        {
            this.form = new WindowsFormsApp1.Form1();
        }
    
        private void SetFormData()
        {
            this.form.Size = new System.Drawing.Size(100, 500);
        }
        public void DoSomeFun()
        {
            this.form.Show();
            myDel del = new myDel(SetFormData);
            this.form.Invoke(del);
        }
    }