关于正常关闭windows服务的问题

sunny906 2013-09-25 12:09:51
有一个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();该怎么写呢? 恳请各位大牛指教。
...全文
214 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
sunny906 2013-09-27
  • 打赏
  • 举报
回复
结贴了,,,
sunny906 2013-09-27
  • 打赏
  • 举报
回复
谢谢jshi123,问题找到了,应该是我的操作系统问题,还是上面的代码,我换台电脑就可以编译运行成功,另外我在论坛里加你关注了。
jshi123 2013-09-26
  • 打赏
  • 举报
回复
如果还不行的话,试下: 先取消注册全部dll,然后全部删掉,重新全部编译,再重新注册。
jshi123 2013-09-26
  • 打赏
  • 举报
回复
检查你的服务类是否有无参数的构造方法,com+需要无参构造。 类应标记为: [System.EnterpriseServices.Transaction(System.EnterpriseServices.TransactionOption.Required)] 类应从 System.EnterpriseServices.ServicedComponent 派生
sunny906 2013-09-26
  • 打赏
  • 举报
回复
jshi123说的对,用事务是最可靠的。 我后来用COM+做事务处理的,snk、dll这些文件也都生成了,而且dll文件也注册了,但是在客户端实例化dll里的对象时,总是报错“CoCreateInstance返回了意外类型”,不知道是什么原因?
jshi123 2013-09-26
  • 打赏
  • 举报
回复
实在是看不出有什么问题。 要不然你把你的程序简化下做个测试项目,找个云盘上传一下,我这里再测试一下。
sunny906 2013-09-26
  • 打赏
  • 举报
回复
嗯,试过了,我把COM+应用程序里的MyCom删掉,然后直接运行客户端自动注册同时执行代码,还是“CoCreateInstance返回了意外类型,应为MyCom类型,却返回了_SomeObject类型”这个异常。 我的操作系统是XP,应该是32位的
jshi123 2013-09-26
  • 打赏
  • 举报
回复
你试过取消注册让.net动态自动注册也不行吗? 你的机器是32位还是64位的?
sunny906 2013-09-26
  • 打赏
  • 举报
回复
嗯嗯,好的,谢谢哈,,这个问题困扰我两天了
jshi123 2013-09-26
  • 打赏
  • 举报
回复
哦,我看错了,你就是这样用的,我再看看。
jshi123 2013-09-26
  • 打赏
  • 举报
回复
如果你是在.net程序中调用,应该不需要字节去实例化com组件,可以引用项目后,直接这样: var myCom = new MyCom(); myCom.ExcuteSQL(); 运行时.net企业服务会自动去注册。
sunny906 2013-09-26
  • 打赏
  • 举报
回复
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.snk 3、修改AssemblyInfo.cs文件:[assembly:AssemblyKeyFile(“mycom.snk”)];密钥在同一个目录下面 4、编译生成mycom.dll 5、注册COM+组件:regsvcs mycom.dll 上面的操作都没有异常,在组件服务里的COM+应用程序里可以看到mycom组件,但是在客户端添加mycom的引用之后实例化MyCom对象:MyCom com=new Mycom();执行到这条语句的时候就报“CoCreateInstance返回了意外类型,应为MyCom类型,却返回了_SomeObject类型”。 于是我就把COM+应用程序里的mycom组件删掉,然后提示同样的异常“CoCreateInstance返回了意外类型,应为MyCom类型,却返回了_SomeObject类型”,估计是组件没有注册成功,不知道在哪里可以看到注册好的组件的GUID之类的,注册表里也没有。
jshi123 2013-09-25
  • 打赏
  • 举报
回复
把操作1和操作2写在同一个transaction中。
jshi123 2013-09-25
  • 打赏
  • 举报
回复
使用TransactionScope实现多数据库连接事务操作 或者搜索“c# 跨数据库事务处理”或“c# 分布式事务处理” 事务方法是最可靠的,其它方法就算能保证关闭前等待,但不能保证断电。
sunny906 2013-09-25
  • 打赏
  • 举报
回复
尝试过用标识,但是结果不理想,,操作1和操作2是不同的数据库,TransactionScope事务下的数据库得是同种类型的数据库,不知道哪种transaction的事务可以同时操作不同的数据库
弱水垂钓 2013-09-25
  • 打赏
  • 举报
回复
可能onStop里的互斥有一个超时会好一点
弱水垂钓 2013-09-25
  • 打赏
  • 举报
回复
以下说的只是我的想法,没实际测试 加一个标识,是否要停止服务,如果服务正常运行,不是要停止 那么就循环读和写, 读出来往别的表里写前引用互斥, mutex.WaitOne 写完了mutex.ReleaseMutex(), 以此循环, 在onStop 一样引用mutex.WaitOne, 把标识置为反状态 最后mutex.ReleaseMutex()
sunny906 2013-09-25
  • 打赏
  • 举报
回复
谢谢jshi123,因为是不同的数据库操作,我试试TransactionScope

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧