对象引用不设置到对象的实例 - WCF服务和委托(WCF委托进行实例化之前托管) [英] Object reference not set to an instance of an object - WCF Service and Delegates (WCF Hosted before Delegate is instantiated)

查看:654
本文介绍了对象引用不设置到对象的实例 - WCF服务和委托(WCF委托进行实例化之前托管)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的代表,让我的服务抓住存储在我的表单的字符串。
当我运行的代码我的服务日志的状态如下:

I am using delegates to allow my service to grab a string that is stored in my form. When I run the code my service log states the following:

System.NullReferenceException:对象引用未设置为一个实例。对象

指着 diData.DIDataCompressed = GetDIData();

我试过在设置断点数据服务器=新ModelDataService();在我的窗体的构造。并注意到我的WCF服务启动(我得到了弹出窗口WcfSvcHost在托盘也在WCF服务主机窗口它说ModelDataService已启动)我的窗体构造函数的代码运行之前,因此委托显然已经没有实例。 更新:服务是我Program.cs中的Main()方法被调用(启动形式方法)之前被启动。另外,我的解决方案的唯一的启动项目是我的形式!

I tried setting a breakpoint at DataServer = new ModelDataService(); in my form's constructor. And noticed that my WCF service was started (I got the popup from WcfSvcHost in tray and also in the WCF Service Host window it says ModelDataService has been started) before my form's constructor's code was run, so the delegate had obviously not been instantiated. Update: The Service is being started before the Main() method in my Program.cs is called (the method that starts the form). Also, my solution's only start up project is my form!

我怎样才能让我的WCF服务只有起动时,我的形式加载(这样我就可以设置委托正确)

How can I get my WCF Service to only start when my form loads (so I can set the delegate correctly)?

下面是我的WCF服务代码:

Here's my WCF Service Code:

[ServiceBehavior(UseSynchronizationContext = false, InstanceContextMode = InstanceContextMode.Single)]
public class ModelDataService : IModelData
{
    public delegate string GetData();
    public GetData GetDIData { get; set; }

    public ModelDataService()
    {
    }

    public DIData GetDData()
    {
        DIData diData = new DIData();

        diData.DIDataCompressed = GetDIData(); // **** error points here

        return diData;
    }
}

[DataContract]
public class DIData
{
    [DataMember]
    public string DIDataCompressed;
}

和我的表单代码应该启动该服务:

And my form code that should start the service:

public partial class ScraperForm : Form
{
    ServiceHost Host;
    ModelDataService DataServer;

    string DIData;

    public ScraperForm()
    {
        InitializeComponent();

        #region Start Data Server
        DataServer = new ModelDataService(); // I set breakpoint here
        DataServer.GetDIData = new ModelDataService.GetData(this.GetDIData);

        Host = new ServiceHost(DataServer, new Uri[]
            {
                new Uri("http://localhost:8000")
            });

        Host.AddServiceEndpoint(typeof(IModelData),
            new BasicHttpBinding(),
            "ModelData");

        Host.Open();

        #endregion

        DIData = "";
    }

    public string GetDIData() 
    {
        return DIData; // This is updated on a timer
    }



我的App.config

My App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
    </appSettings>
    <system.web>
        <compilation debug="true" />
    </system.web>
    <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
    <system.serviceModel>
        <services>
            <service name="SoccerModelService.ModelDataService">
                <endpoint address="" binding="basicHttpBinding" 
                          bindingConfiguration="BasicHttpBinding" 
                          contract="SoccerModelService.IModelData"
                          name ="BasicHttpBinding_IModelData">
                    <identity>
                        <dns value="localhost"/>
                    </identity>
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8000/ModelData/"/>
                        <!--//localhost:8733/Design_Time_Addresses/ModelDataService/Service1/" /> -->
                    </baseAddresses>
                </host>
            </service>
            <!--><service name="SoccerModelService.ModelDataService" behaviorConfiguration="debug">
            </service> -->
        </services>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
                    <readerQuotas maxDepth="32" maxStringContentLength="8388608" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8000/ModelData/" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding" contract="SoccerModelService.IModelData"
                name="EndPoint" behaviorConfiguration="EndpointBehaviour" />
                <!--<endpoint address="http://localhost:8000/ModelData" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding" name="EndPoint" behaviorConfiguration="EndpointBehaviour" /> -->
        </client>
        <behaviors>
            <serviceBehaviors>
                <behavior>
                    <!-- To avoid disclosing metadata information, 
          set the values below to false before deployment -->
                    <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
                    <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
                    <serviceDebug includeExceptionDetailInFaults="False" />
                </behavior>
                <behavior name="debug">
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>
            <endpointBehaviors>
                <behavior name="EndpointBehaviour">
                    <dataContractSerializer maxItemsInObjectGraph="2147483647" />
                </behavior>
            </endpointBehaviors>
        </behaviors>
    </system.serviceModel>

    <!-- Trace-->
    <system.diagnostics>
        <sources>
            <source name="System.ServiceModel" switchValue="Warning" propagateActivity="true" >
                <listeners>
                    <add name="xml"/>
                </listeners>
            </source>

            <source name="myUserTraceSource" switchValue="Warning, ActivityTracing">
                <listeners>
                    <add name="xml"/>
                </listeners>
            </source>
        </sources>

        <sharedListeners>
            <add name="xml"
                 type="System.Diagnostics.XmlWriterTraceListener"
                 initializeData="TraceLog.svclog" />
        </sharedListeners>
        <trace autoflush="true" />
    </system.diagnostics>

</configuration>



感谢您的帮助!

Thanks for your help!

< STRONG>更新

我添加了一个加载事件对我的形式。我仍然得到同样的错误。我想在我的Program.cs的Main()方法中设置断点为我的形式(即启动的形式方法),并在服务启动Program.cs中的主要方法,甚至被调用之前!

I added a load event to my form. I am still getting the same error. I tried setting a breakpoint on the Main() method in my Program.cs for my form (the method that starts the form) and the service is started before the main method in Program.cs is even called!

难道问题是该服务的一个新实例创建的每个我的客户端调用服务的时间?我已经将它设置成是单身,但我已不正确地做呢?

Could the problem be that a new instance of the service is created every time my client calls the service? I have set it up to be a singleton but have I done it incorrectly?

更新2

我觉得我可能不小心让自己的项目中WCF服务应用程序,而不是一个WCF服务库(我可能拥有一个表单内)。我的项目的bin包含项目的名字一个.dll。我认为,这意味着,这的确是一个图书馆。请纠正我,如果我错了。

I thought that I may have accidentally made my project a WCF Service Application, and not a WCF Service Library (which I could host inside a form). The bin for my project contains a .dll in the project's name. I believe that this means that it is indeed a Library. Please correct me if I'm wrong.

再次感谢!

推荐答案

我的答案是基于在评论中提供的补充资料。

这是非常不寻常的WCF服务的访问用户界面窗口或其组件作为一个服务应该是在后台运行在服务器上,不能与用户界面干扰(有很多调试服务时,谁使用的消息框,忘了部署解决方案之前删除他们的程序员的故事。至于它应该在消息框挡住了这个结束。服务器)

出于这个原因,我建议下列方法(顺序是按意向):

My answer is based upon the additional information provided in the comments.
It is very unusual to have a WCF service access a user interface window or its components as a service is supposed to run in the background on a server and must not interfere with the user interface (there are lots of stories of programmers who used message boxes when debugging a service and forgot to remove them before deploying the solution. As it was supposed to, this ended in message boxes blocking the server).
For that reason I'd suggest the following approaches (the order is by intent):


  1. 尝试做刮痧服务中的用户界面,更低的方式,例如:通过使用Web客户端或类似的东西,以获得原始的HTML文件,并分析其内容。

  2. 如果你需要有一个用户的web浏览器,以互动,能够得到的文档你想放弃(例如身份验证),因为你使用一个单独的应用程序现在将结果存储在数据库中。但是从服务独立地使用应用程序。该服务可以仅返回被存储在数据库中(也许使用时间戳,使得当数据被检索的用户被告知,如果数据太旧可以反应)中的数据。

  3. 自托管应用程序中的WCF服务。由你可以结合你想要的方式应用程序和服务。缺点是,你只能只要访问该服务在应用程序运行 - 但您将能够控制和同步应用程序的生命周期,在你想要的方式服务

  4. 如果没有第一个方法的工作,转身你的依赖关系,以便服务启动应用程序,而不是相反。 WCF服务将只运行一次,并控制应用程序的中心位置。如果您尝试让应用程序在服务器上注册本身,你麻烦,如果一个用户启动应用程序多次运行。

  1. Try to do the scraping in the service a UI-less way, e.g. by using WebClient or something similar to get the raw HTML document and analyze its content.
  2. If you need to have a user interact with the WebBrowser in order to be able to get to the document you want to scrap (e.g. for authentication), use a separate application as you do now and store the result in a database. But use the application independently from the service. The service can return only the data that is stored in the database (maybe with a timestamp so that users are informed when the data was retrieved and can react if the data is too old).
  3. Self host the WCF service in the application. By that you can combine the application and the service in a way you want. Downside is that you can access the service only as long as the application runs - but you will be able to control and sync the lifecycle of the application and the service in the way you want.
  4. If neither of the first approaches work, turn around your dependencies so that the service starts the application and not the other way round. The WCF service will be the central spot that runs only once and controls the application. If you try to have the application register itself with the server, you run in trouble if a user starts the application several times.

一还有一点:你提到要使用委托,让服务来访问应用程序的信息。如果你想拥有的服务,这样的应用程序交互,代表们将无法胜任的应用和服务生活在不同的进程。你可以使用一个双工WCF服务,如果你真的需要这个。但我认为可能性很高,你不会需要从服务访问应用程序,您改制为上面写你的设计了。

One more thing: you mention that you want to use delegates to allow the service to access the information in the application. If you want to have the service interact with the application in this way, delegates won't do the trick as the application and the service live in different processes. You could use a Duplex WCF service if you really need this. But I think the probability is high that you won't need to access the application from the service after you restructured your design as written above.

这篇关于对象引用不设置到对象的实例 - WCF服务和委托(WCF委托进行实例化之前托管)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆