0

我有一个 WCF 服务,我想在其中保存一个在服务运行时创建的 XML 列表,以便在服务关闭后保存,即在重新启动服务时查看它。调用 HTTP POST 时会将项目添加到列表中。但是,当程序中返回列表项的 HTTP GET 方法在重新启动服务后被调用时,它不会显示列表项,因为它们没有保存。我与此问题相关的问题是:

1) 如何保存列表以供将来参考?2)是否有某种机制可以在每次服务关闭时保存此列表,以便在重新启动服务时可以查看?

还有一个指针:我不希望将列表项保存为本地机器上的 xml 文件!

4

1 回答 1

1

Tim 的建议是合理的,但是您不需要自定义服务主机来执行此操作。主要是将数据内容写入持久存储,在更新后的某个时间点。当您收到 POST 时,更新内存中的数据表示,然后将事物写入文件系统上的 xml 文件。

  public void DoPost()
  {
      UpdateData();
      SaveDataToFilesystem();
  }

重新启动时,从文件中读取(如果存在)。

要处理并发,您必须在Update()andSave()方法中锁定数据。

如果系统负载很高,则将“写入文件文件系统”推迟到最多每 10 秒左右一次。

  public void DoPost()
  {
      UpdateData();
      QueueWriteToFilesystem();
  }

  private MyInternalDataType data;
  private DateTime lastWrite = new DateTime(1970,1,1); // init value
  private void QueueWriteToFilesystem()
  {
      ThreadPool.QueueUserWorkItem( MaybeWrite );
  }


  private int delayInMilliseconds = 1000 * 10; // 10 seconds
  private void MaybeWrite()
  {
      System.Threading.Thread.Sleep(delayInMilliseconds);
      lock (data)
      {
          var delta = System.DateTime.Now - lastWrite;
          if (delta < new System.TimeSpan(0, 0, 0, 0, delayInMilliseconds))
          {
              // less than 10s since last write
              // do nothing
              return;
          }
          ActuallySaveToFilesystem();
          lastWrite = System.DateTime.Now;
      }
  }

对于真正的高并发性,您不希望在每个请求中都排队一个新的工作项。相反,您只需使用写入的专用线程。

  public void DoPost()
  {
      UpdateData();
      lastUpdate = System.DateTime.Now;
  }

  private void DedicatedWriter()
  {
      do
      {
          System.Threading.Thread.Sleep(delayInMilliseconds);
          lock (data)
          {
              var delta = lastUpdate - lastWrite;
              if (delta < new System.TimeSpan(0, 0, 0, 0, 200))
              {
                  // small amount of time since prior write;
                  // do nothing
                  return;
              }
              ActuallySaveToFilesystem();
              lastWrite = System.DateTime.Now;
          }
      } while (true);
  }

您还可以使用 AutoResetEvents 来通知编写器线程唤醒。

于 2012-04-26T20:36:41.093 回答