Reputation: 1003
I have a BackgroundWorker
that watches for a WMI notification event to fire. My query looks something like SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name=proccessnamehere
. This query polls for an __InstanceDeletionEvent that meet the WHERE conditions every 2 seconds. Sometimes the process I’m watching takes a while, delaying the event from firing and i would like to cancel it. Everything I’ve read about cancelling BackgroundWorker suggest i use a loop of some sort. However, I’m not sure how to include a loop during a notification event. Is there an alternative way to do this? I played around with a timer but no success
Edit: Code Sample - removed unrelated code
(This will execute against a remote computer)
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();
}
Upvotes: 1
Views: 555
Reputation: 47570
You can't force the termination of a background worker immediately (without using cancellation pending flag), it simply isn't designed in that way.
Task Parallel Library provides that feature.
If you really want to use a BackgroundWorker and achieve your goal below is an option. Probably not the best way to do it..
You can get the get the Thread the BackgroundWorker is running on in the DoWork event save it in a field and you can then abort the thread.
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.
}
}
Reference here for more options
Edit
May be you are looking for something like below.
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;
}
Upvotes: 1