【问题标题】:Cancel BackgroundWorker while waiting for a WMI notification event在等待 WMI 通知事件时取消 BackgroundWorker
【发布时间】:2015-07-20 22:03:15
【问题描述】:

我有一个 BackgroundWorker 来监视 WMI 通知事件的触发。我的查询类似于SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name=proccessnamehere。此查询每 2 秒轮询一次满足 WHERE 条件的 __InstanceDeletionEvent。有时我正在观看的过程需要一段时间,延迟事件触发,我想取消它。我读到的关于取消 BackgroundWorker 的所有内容都建议我使用某种循环。但是,我不确定如何在通知事件中包含循环。有没有其他方法可以做到这一点?我玩了一个计时器,但没有成功

编辑:代码示例 - 删除不相关的代码

(这将针对远程计算机执行)

using System.Management;
private void backGroundWorkerStart_DoWork(object sender, DoWorkEventArgs e)
    {
        object[] args = e.Argument as object[];
        string computerName = args[0].ToString();
        string processName = args[1].ToString();

        ConnectionOptions con = new ConnectionOptions();
        con.Impersonation = ImpersonationLevel.Impersonate;
        con.Authentication = AuthenticationLevel.Default;
        con.EnablePrivileges = true;

        ManagementScope scope = new ManagementScope(String.Format(@"\\{0}\ROOT\CIMV2", computerName), con);

        scope.Connect();

        WqlEventQuery query = new WqlEventQuery(String.Format("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='{0}'", processName));
        ManagementEventWatcher watcher = new ManagementEventWatcher(scope, query);

        ManagementBaseObject baseObject = watcher.WaitForNextEvent();
    }

【问题讨论】:

  • 你能发布你当前代码的(可能是简化的)版本吗?
  • @EricJ。添加了一个简化的示例。希望这是您的要求。

标签: c# .net multithreading wmi backgroundworker


【解决方案1】:

您不能立即强制终止后台工作程序(不使用取消挂起标志),它根本不是以这种方式设计的。

Task Parallel Library 提供了该功能。

如果您真的想使用 BackgroundWorker 并实现您的目标,下面是一个选项。可能不是最好的方法..

您可以在 DoWork 事件中获取 BackgroundWorker 正在运行的线程,并将其保存在一个字段中,然后您可以中止线程。

private Thread _backgroundWorkerThread;

public void StartBackgroundWorker()
{
    BackgroundWorker backgroundWorker = new BackgroundWorker();
    backgroundWorker.DoWork += DoWork;
    backgroundWorker.RunWorkerAsync();
}

public void AbortBackgroundWorker()
{
    if(_backgroundWorkerThread != null)
        _backgroundWorkerThread.Abort();
}

void DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        _backgroundWorkerThread = Thread.CurrentThread;

        // Do your work...
    }
    catch(ThreadAbortException)
    {
        // Do your clean up here.
    }
}

更多选项请参考here

编辑

也许你正在寻找类似下面的东西。

WqlEventQuery query = new WqlEventQuery(String.Format("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='{0}'", processName));
            ManagementEventWatcher watcher = new ManagementEventWatcher(scope, query);

            ManagementBaseObject baseObject = watcher.WaitForNextEvent();

            if (myBackgroundWorkder.CancellationPending)
            {
                e.Cancel = true;
                watcher.Stop();
                return 0;
            }

【讨论】:

  • 感谢您的回复。我知道我不能强制终止线程。我确实通过 MSDN 上提供的示例知道我可以设置一个循环来观察 CancellationPending 标志是否变为 True,然后设置 CancelEventArgs.Canel = True 这应该触发线程结束。我不知道如何设置一个循环来检查 CancellationPending 标志是否发生变化。
  • @HiTech:看看我的更新。可能你正在寻找类似的东西......
  • 感谢您的编辑。在 watcher.WaitForNextEvent() 之后运行检查的问题是它在事件触发之前不会运行。太晚了。
  • 如果这是我唯一的选择,如果我只是远程终止进程并让事件观察程序的线程自然结束可能会更好。感谢您的帮助@CharithJ
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多