如何在后台工作者类之外访问此线程的取消挂起



我有一个Windows服务,可以创建许多BackgroundWorkers。这些 BackgroundWorker 的 DoWork 处理程序只包含 SomeObject.DoSomeWork(),并且该方法(即 DoSomeWork)不引用 BackgroundWorker。阻塞工作发生得更深很多层。在具有阻塞工作的方法中,我想添加逻辑来测试拥有后台工作线程的取消挂起。如何???

我不想重构所有类来传递对 BackgroundWorker 的引用,我希望能够编写这样的东西;

(BackgroundWorker(Thread.CurrentThread)).CancellationPending

但这显然不起作用,因为BackgroundWorker 本身不是一个线程。

我没有尝试过任何东西,因为我没有想到要尝试的任何东西。我用谷歌搜索了很多,读了很多书,但没有找到任何能为我指明正确方向的东西。可能是不可能(至少不可能在不变得太黑客的情况下),在这种情况下,我将不得不考虑一种不同的方法来解决问题,但我需要一个比我更聪明的人告诉我这是不可能的:)

有一个

技巧可以做到这一点。仅在别无选择的情况下才使用此功能。可以使用线程局部变量使BackgroundWorker在当前线程上的任何位置可用。

[ThreadStatic]
static BackgroundWorker bw;

然后,您需要维护此变量:

try {
 bw = ...;
 DoSomeWork();
}
finally { bw = null; }

你可以有一个集合Dictionary<MyObject, BackgroundWorker>,用于存储对象和后台工作线程引用,然后是一个扩展方法:

public static void CancelWork(this MyObjectObject myObj)
{
  var kvp = dictionary.FirstOrDefault(o => o.Key.equals(myObj));
  if(kvp.Key == null) return;
  // TODO
  // Call the background worker cancellation from the kvp.Value
}

可以从您的对象调用此扩展方法,如下所示:

this.CancelWork();

与@Panda的答案类似,您可以有一个静态Dictionary<int, BackgroundWorker> workers;集合并将其填充在DoWork处理程序的开头:

workers[Thread.CurrentThread.ManagedThreadId] = sender as BackgroundWorker;

然后在您的DoSomeWork中使用它,如下所示:

bw = workers[Thread.CurrentThread.ManagedThreadId];
// use bw.CancellationPending

但请注意同步此集合,最好使用 ConcurrentDictionary .还有一件事,您应该确保您的DoWork处理程序仅在一个线程中运行,以便正常工作。

最新更新