C# 具有一次性参数的后台工作程序
我有一个后台工作程序,它接收一个一次性对象作为参数。在using块内调用C# 具有一次性参数的后台工作程序,c#,.net,C#,.net,我有一个后台工作程序,它接收一个一次性对象作为参数。在using块内调用RunWorkerAsync方法 下面是一个简化的代码示例 private void SearchTest(string filter) { bgWorker.DoWork += bgWorker_DoWork; using (DirectoryEntry dirEntry = new DirectoryEntry()) { using
RunWorkerAsync
方法
下面是一个简化的代码示例
private void SearchTest(string filter)
{
bgWorker.DoWork += bgWorker_DoWork;
using (DirectoryEntry dirEntry = new DirectoryEntry())
{
using (var search = new DirectorySearcher(dirEntry))
{
search.SearchScope = SearchScope.Subtree;
search.Filter = string.Format("(&(objectCategory=group)(cn={0}))", filter);
bgWorker.RunWorkerAsync(search);
}
}
}
void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
var searcher = (DirectorySearcher) e.Argument;
var reportList = new List<String>();
bgWorker.ReportProgress(0);
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult result in results)
{
reportList.Add(result.Properties["cn"][0]);
bgWorker.ReportProgress(1);
}
e.Result= reportList;
}
该对象肯定是在using块的末尾被释放的,因此您的后台工作程序正在使用一个已释放的实例
我猜测为什么它仍然有效是因为
DirectorySearcher
只有一个Dispose
方法,因为它派生自组件
,实际上没有使用它,也就是说,Dispose
不做任何事情,这个类的方法也不关心Dispose是否被调用。这看起来肯定会失败,ObjectDisposedException
…您不能在这里使用using语句,对象将在线程运行之前或运行时被释放。卡布姆。您需要在DoWork事件处理程序或RunWorkerCompleted事件处理程序中处理它。@HansPassant:我认为在这种特定情况下没有kaboom,请参阅我的答案。@Hans Passant我知道这看起来很奇怪,但这段代码正在工作。@Guish它是靠运气工作的。未来版本的.Net可能会开始抛出一个ObjectDisposedException
,因此一定要使用将移动到worker。我查看了FindAll()
的代码,它没有检查对象是否已被释放,这可能解释了为什么它没有抛出异常。看起来很不安全,在未来的版本中可能会中断。@Matthew Watson:我想改为在后台工作程序完成时执行dispose。它使用dispose(),下面有一个Marshal.ReleaseComObject()调用。@Daniel Higarth dispose方法实际上调用了基组件dispose
methodYeah,我现在也看了一下代码:它做了一些事情,但显然没有影响OP使用的方法的功能。
private void SearchTest(string filter)
{
bgWorker.DoWork += bgWorker_DoWork;
using (DirectoryEntry dirEntry = new DirectoryEntry())
{
using (var search = new DirectorySearcher(dirEntry))
{
search.SearchScope = SearchScope.Subtree;
search.Filter = string.Format("(&(objectCategory=group)(cn={0}))", filter);
////////////////////
search.Dispose();
////////////////////
var reportList = new List<String>();
SearchResultCollection results = searcher.FindAll();//Still work with the disposed instance
foreach (SearchResult result in results)
{
reportList.Add(result.Properties["cn"][0]);
}
}
}
}