如何在C#应用程序中取消正在执行的SSIS包
取消通过DtsContainer.Execute运行的包部署模型SSIS包的实现方案
你当前使用的Microsoft.SqlServer.Dts.Runtime.DtsContainer.Execute方法是同步阻塞调用,直接在UI线程执行时既会卡住界面,也无法响应取消操作,可通过以下成熟方案实现运行中包的取消,完全兼容包部署模型:
- 执行逻辑与UI线程隔离:将SSIS包的顺序执行逻辑放到独立后台线程运行,WinForms下推荐用
Task或BackgroundWorker实现,避免阻塞UI线程,同时保证UI上的取消按钮可以正常响应点击。 - 自定义事件类实现取消监听:SSIS运行时在包执行全周期会定期触发
IDTSEvents.OnQueryCancel回调询问是否需要终止执行,你可以自定义继承自DefaultEvents的事件类,增加公开的取消标记属性,重写OnQueryCancel方法,当检测到取消标记为真时,将回调参数中的cancel标识设为true,SSIS运行时收到该标识后会安全终止当前正在运行的包,自动完成资源回收、事务回滚等清理操作。
注意:
OnQueryCancel为轮询触发,触发间隔由当前正在执行的SSIS任务类型决定,长耗时的数据流、SQL执行任务触发间隔通常在数秒级别,取消操作会存在短暂延迟,属于正常表现,不要为了追求实时响应强杀执行线程。
- 取消触发逻辑:在WinForms窗体上添加取消按钮,按钮点击事件中仅需要将自定义事件类实例的取消标记属性设为true即可,不需要额外操作。顺序执行多个包的场景下,可以在外层包遍历循环中增加取消标记判断,当前包终止后直接跳过后续未执行的包即可。
简化实现代码
自定义事件类实现:
using Microsoft.SqlServer.Dts.Runtime; public class SsisExecutionEvents : DefaultEvents { /// <summary> /// 外部设置该属性为true即可触发SSIS包取消 /// </summary> public bool IsCancelRequested { get; set; } = false; public override bool OnQueryCancel(string eventSourceName, string eventSourceGuid, ref bool cancel) { if (IsCancelRequested) { cancel = true; return true; } return base.OnQueryCancel(eventSourceName, eventSourceGuid, ref cancel); } }
窗体侧执行与取消逻辑:
private SsisExecutionEvents _currentExecutionEvents; private readonly Application _ssisApp = new Application(); private async void btnStartExecute_Click(object sender, EventArgs e) { _currentExecutionEvents = new SsisExecutionEvents(); btnStartExecute.Enabled = false; btnCancel.Enabled = true; // 后台执行避免卡UI await Task.Run(() => { foreach (string packagePath in GetYourPackagePathList()) { // 已收到取消请求则跳过后续包 if (_currentExecutionEvents.IsCancelRequested) break; Package pkg = _ssisApp.LoadPackage(packagePath, null); // 传入自定义事件实例执行包 pkg.Execute(null, null, _currentExecutionEvents, null, null); } }); btnStartExecute.Enabled = true; btnCancel.Enabled = false; } private void btnCancel_Click(object sender, EventArgs e) { if (_currentExecutionEvents != null) { _currentExecutionEvents.IsCancelRequested = true; } }
注意事项
- 严禁通过
Thread.Abort等方式强行终止执行SSIS包的线程,这种方式会跳过SSIS运行时的资源清理流程,可能导致数据库连接泄漏、临时文件残留、事务未正常回滚等问题,甚至影响后续包的正常执行。 - 该方案不需要修改现有SSIS包的任何配置,仅需要替换传入
Execute方法的IDTSEvents参数即可,对包部署模型的SSIS包全版本兼容。
内容的提问来源于stack exchange,提问作者alj
相关产品推荐
相关产品推荐

