我有一个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
处理程序仅在一个线程中运行,以便正常工作。