【问题标题】:WCF streaming mode issueWCF 流模式问题
【发布时间】:2009-08-17 12:56:26
【问题描述】:

我使用流模式使用 basicHttpBinding 在 IIS 中托管 WCF 服务。 WCF Web 服务使用 ADO.Net 查询后端 SQL Server 2008,并向 WCF 服务的客户端返回一个 DataTable。

我对 WCF 流模式的理解是,

  1. WCF 流模式应该只在客户端和服务器端使用恒定数量的内存;
  2. WCF 流模式应该能够在客户端和服务器之间传输任意数量的数据。

我的理解正确吗?

如果是,我的以下示例违反了这两个规则,我观察到两个违规行为,

  1. 我发现我的以下示例继续消耗内存(从任务管理器的性能选项卡中,内存使用量增加)。我在同一台机器上运行客户端和服务器。那么,WCF 流模式不使用固定数量的内存吗?

  2. 当传输10M行的DataTable时,下面贴出异常。但是传输 1M 行就可以了。那么,WCF 流模式不能传输任意数量的数据?

有什么想法吗?

异常信息:

接收时发生错误 HTTP 响应 http://labmachine1/service.svc。这 可能是由于服务端点 绑定不使用 HTTP 协议。 这也可能是由于 HTTP 请求上下文被中止 服务器(可能是由于服务 关闭)。查看服务器日志 更多细节。

{"底层连接已关闭:发生意外错误 接收。"}

这是我在服务器端的全部源代码,对于我在 web.config 中托管的服务器,默认值没有变化。由于我在 IIS 中托管,因此我使用的是 basicHttpBinding。

public class StudentManagement : IStudentManagement
{
    public DataTable Poll(int Id)
    {
        return MakeParentTable();
    }

    private DataTable MakeParentTable()
    {
        // Create a new DataTable.
        System.Data.DataTable table = new DataTable("ParentTable");
        // Declare variables for DataColumn and DataRow objects.
        DataColumn column;
        DataRow row;

        // Create new DataColumn, set DataType, 
        // ColumnName and add to DataTable.    
        column = new DataColumn();
        column.DataType = System.Type.GetType("System.Int32");
        column.ColumnName = "id";
        column.ReadOnly = true;
        column.Unique = true;
        // Add the Column to the DataColumnCollection.
        table.Columns.Add(column);

        // Create second column.
        column = new DataColumn();
        column.DataType = System.Type.GetType("System.String");
        column.ColumnName = "ParentItem";
        column.AutoIncrement = false;
        column.Caption = "ParentItem";
        column.ReadOnly = false;
        column.Unique = false;
        // Add the column to the table.
        table.Columns.Add(column);

        // Make the ID column the primary key column.
        DataColumn[] PrimaryKeyColumns = new DataColumn[1];
        PrimaryKeyColumns[0] = table.Columns["id"];
        table.PrimaryKey = PrimaryKeyColumns;

        // Create three new DataRow objects and add 
        // them to the DataTable
        for (int i = 0; i <= 10000000; i++)
        {
            row = table.NewRow();
            row["id"] = i;
            row["ParentItem"] = "ParentItem " + i;
            table.Rows.Add(row);
        }

        return table;
    }
}

客户端代码:

static void Main(string[] args)
{
    StudentIdentifier identifier = new StudentIdentifier();
    identifier.Id = 100;
    StudentManagementClient client = new StudentManagementClient();

    DataTable student = client.Poll(identifier);

    Console.WriteLine(student.Rows.Count);
}

客户端app.config的流模式配置,

    <basicHttpBinding>
      <binding name="BasicHttpBinding_IStudentManagement" closeTimeout="00:01:00"
        openTimeout="00:20:00" receiveTimeout="01:00:00" sendTimeout="01:00:00"
        allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
        maxBufferSize="1500000000" maxBufferPoolSize="1500000000" maxReceivedMessageSize="1500000000"
        messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed"
        useDefaultWebProxy="true">
        <readerQuotas maxDepth="1500000000" maxStringContentLength="1500000000"
          maxArrayLength="1500000000" maxBytesPerRead="1500000000" maxNameTableCharCount="1500000000" />
        <security mode="None">
          <transport clientCredentialType="None" proxyCredentialType="None"
            realm="" />
          <message clientCredentialType="UserName" algorithmSuite="Default" />
        </security>
      </binding>
    </basicHttpBinding>

流模式的服务器端 web.config,

  <basicHttpBinding>
    <binding name="BasicHttpBinding_IStudentManagement" closeTimeout="00:01:00"
        openTimeout="00:20:00" receiveTimeout="01:00:00" sendTimeout="01:00:00"
        allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
        maxBufferSize="1000000000" maxBufferPoolSize="1000000000" maxReceivedMessageSize="1000000000"
        messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed"
        useDefaultWebProxy="true">
      <readerQuotas maxDepth="32" maxStringContentLength="1000000000" maxArrayLength="1000000000"
          maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None"
            realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>
  </basicHttpBinding>

【问题讨论】:

    标签: c# .net wcf visual-studio-2008 datatable


    【解决方案1】:

    在流模式下,您必须使用 system.io.stream 作为返回类型或参数类型。显然,你没有这样做。

    【讨论】:

      【解决方案2】:

      maxBufferSize 属性限制了 WCF 在发送/接收流数据时使用的内存量。但是,您正在将大型对象加载到内存中,然后再将它们发送到客户端。

      我建议您首先使用 DTO(数据传输对象)将数据发送到客户端,并且如果您需要向客户端发送大量数据,您可以实施分页机制以可管理的块传输数据。

      理论上,您可以使用 WCF 向客户端发送 1000 万条记录,但实际上,客户端几乎不需要那么多数据,尤其是一次。

      【讨论】:

        猜你喜欢
        • 2011-01-28
        • 1970-01-01
        • 2010-12-18
        • 2011-09-29
        • 2012-09-29
        • 2011-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多