有一个windows服务,它做的事情是不断地从A数据表里读数据,然后把读出来的数据添加到B数据表,最后删除A数据表的数据,大致代码如下:while(true)
{
  using(SqlDataReader reader=...) //从A数据表读数据
  {
    while(reader.Read())
   {
     insert into b...; //1、把读出来的数据写到B数据表
      delete from a ...; //2、删除A数据表数据
    }
 }
}当正常停止服务的时候,代码可能刚执行完添加操作1,而删除操作2还没有执行,此时服务就被关闭了;现在的问题是如何才能保证关闭服务的时候,等每一次的操作1和操作2都执行完后再关闭服务?在服务的方法里protected override void OnStop();该怎么写呢? 恳请各位大牛指教。

解决方案 »

  1.   

    把操作1和操作2写在同一个transaction中。
      

  2.   

    谢谢jshi123,因为是不同的数据库操作,我试试TransactionScope
      

  3.   

    以下说的只是我的想法,没实际测试加一个标识,是否要停止服务,如果服务正常运行,不是要停止
    那么就循环读和写,
    读出来往别的表里写前引用互斥, mutex.WaitOne
    写完了mutex.ReleaseMutex(),
    以此循环, 在onStop 一样引用mutex.WaitOne, 把标识置为反状态
    最后mutex.ReleaseMutex()
      

  4.   

    可能onStop里的互斥有一个超时会好一点
      

  5.   

    尝试过用标识,但是结果不理想,,操作1和操作2是不同的数据库,TransactionScope事务下的数据库得是同种类型的数据库,不知道哪种transaction的事务可以同时操作不同的数据库
      

  6.   

    使用TransactionScope实现多数据库连接事务操作
    或者搜索“c# 跨数据库事务处理”或“c# 分布式事务处理”事务方法是最可靠的,其它方法就算能保证关闭前等待,但不能保证断电。
      

  7.   

    jshi123说的对,用事务是最可靠的。
    我后来用COM+做事务处理的,snk、dll这些文件也都生成了,而且dll文件也注册了,但是在客户端实例化dll里的对象时,总是报错“CoCreateInstance返回了意外类型”,不知道是什么原因?
      

  8.   

    检查你的服务类是否有无参数的构造方法,com+需要无参构造。
    类应标记为:
    [System.EnterpriseServices.Transaction(System.EnterpriseServices.TransactionOption.Required)] 
    类应从 System.EnterpriseServices.ServicedComponent 派生
      

  9.   

    如果还不行的话,试下:
    先取消注册全部dll,然后全部删掉,重新全部编译,再重新注册。
      

  10.   

    1、代码如下:  using System;
      using System.EnterpriseServices;
      using System.Data.SqlClient;
      using System.Data.OracleClient;  namespace MyCom
      {
       [ Transaction(TransactionOption.Required) ]
      public class MyCom : ServicedComponent
      {
      public MyCom() {}  public void ExecuteSQL()
      {
      try
      {
      ... //向Oracle数据表中插入一条记录
        ... //从Sql数据表中删除相应的这条记录
         ContextUtil.SetComplete();
      }
      catch(Exception e)
      {
      ContextUtil.SetAbort();
      }
      }
    }
    }
    2、创建密钥:sn –k mycom.snk3、修改AssemblyInfo.cs文件:[assembly:AssemblyKeyFile(“mycom.snk”)];密钥在同一个目录下面4、编译生成mycom.dll5、注册COM+组件:regsvcs mycom.dll上面的操作都没有异常,在组件服务里的COM+应用程序里可以看到mycom组件,但是在客户端添加mycom的引用之后实例化MyCom对象:MyCom com=new Mycom();执行到这条语句的时候就报“CoCreateInstance返回了意外类型,应为MyCom类型,却返回了_SomeObject类型”。
    于是我就把COM+应用程序里的mycom组件删掉,然后提示同样的异常“CoCreateInstance返回了意外类型,应为MyCom类型,却返回了_SomeObject类型”,估计是组件没有注册成功,不知道在哪里可以看到注册好的组件的GUID之类的,注册表里也没有。
      

  11.   

    如果你是在.net程序中调用,应该不需要字节去实例化com组件,可以引用项目后,直接这样:
    var myCom = new MyCom();
    myCom.ExcuteSQL();
    运行时.net企业服务会自动去注册。
      

  12.   

    你试过取消注册让.net动态自动注册也不行吗?
    你的机器是32位还是64位的?
      

  13.   

    嗯,试过了,我把COM+应用程序里的MyCom删掉,然后直接运行客户端自动注册同时执行代码,还是“CoCreateInstance返回了意外类型,应为MyCom类型,却返回了_SomeObject类型”这个异常。我的操作系统是XP,应该是32位的
      

  14.   

    谢谢jshi123,问题找到了,应该是我的操作系统问题,还是上面的代码,我换台电脑就可以编译运行成功,另外我在论坛里加你关注了。