【问题标题】:Passing collection from backgroundworker DoWork to backgroundworker Completed and perform a foreach将集合从 backgroundworker DoWork 传递给 backgroundworker 完成并执行一次 foreach
【发布时间】:2013-08-07 18:15:20
【问题描述】:

我的目标是:

  • 用户在组合框中输入完整或部分计算机名
  • 按钮单击事件启动后台工作人员将计算机名传递给 DoWork 方法
  • DoWork 方法在 ActiveDirectory 中搜索计算机名并将集合传递给 WorkerCompleted 方法
  • WorkerCompleted 方法将每个计算机名添加到组合框项中。

我的错误出现在我的 backgroundWorker_RunWorkerCompleted 方法的 foreach 循环中。

  • “foreach 语句无法对 'object' 类型的变量进行操作,因为 'object' 不包含 'GetEnumerator' 的公共定义”

如果我执行 MessageBox.Show(results.First().ToString());在 DoWork 方法中,我可以查看集合中的第一个计算机名。

如果我执行 MessageBox.Show(e.Result.ToString());在 DoWork 和 WorkerCompleted 方法中,我得到了这个:

  • “System.DirectoryServices.AccountManagement.PrincipalSearchResult`1[System.DirectoryServices.AccountManagement.Principal]”

任何关于这方面的指导将不胜感激!

    private void button1_Click(object sender, EventArgs e)
    {
        //Saves computername entered by user to pass into DoWork method
        string PCName = comboBox1.Text;

        //Start background thread passing computer to the Dowork method
        backgroundWorker1.RunWorkerAsync(PCName);
    }
   
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {                 
        using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
        {
            //Setup Filter
            ComputerPrincipal computer = new ComputerPrincipal(ctx);
            computer.Name = "*" + e.Argument + "*";

            //Search for PC
            PrincipalSearcher ps = new PrincipalSearcher();
            ps.QueryFilter = computer;

            //Get Results
            PrincipalSearchResult<Principal> results = ps.FindAll();
                 
            //results will be passed to RunWorkerCompleted
            e.Result = results;                
        }
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //Add each computername to combobox
        foreach (object PC in e.Result) // <--------------- ERROR HERE!
        {
            comboBox1.Items.Add(PC.ToString());
        }                            
    }
}

【问题讨论】:

    标签: c#


    【解决方案1】:

    您必须将已完成处理程序中的 e.Resultobject 转换为 PrincipalSearchResult&lt;Principal&gt; 才能遍历它。

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //Add each computername to combobox
        PrincipalSearchResult<Principal> results = (PrincipalSearchResult<Principal>)e.Result;
        foreach (Principal PC in results)
        {
            comboBox1.Items.Add(PC.ToString());
        }                            
    }
    

    编辑:

    PrincipalSearcher 不能用于Background Worker,因为它使用需要单线程单元(STA) 的COM 组件。后台工作线程在多线程单元 (MTA) 中运行。 ApartmentState 可以使用Thread.SetApartmentState 设置,但必须在线程启动前调用(因此不能用于更改BackgroundWorker 工作线程的ApartmentState)。

    【讨论】:

    • 感谢您的回复!添加您的代码并得到与 Blau 相同的错误。 System.DirectoryServices.dll 中出现“System.InvalidCastException”类型的异常,但未在用户代码中处理附加信息:无法将“System.__ComObject”类型的 COM 对象转换为接口类型“IDirectorySearch”。此操作失败,因为 IID 为“{109BA8EC-92F0-11D0-A790-00C04FD8D5A8}”的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:不支持此类接口(来自 HRESULT 的异常:0x80004002 (E_NOINTERFACE)) .
    • 那是丑陋的。这是因为PrincipalSearcher 使用 COM 组件,无法从 Background Worker 安全使用。
    • 开枪!这样就解决了。现在研究一下解决方法。我感谢您的帮助!我会 +1 你的帖子,但我需要更多代表。
    • 只需将答案标记为已接受以供其他人查看。单击答案旁边的复选标记,将其从灰色切换为已填充。
    【解决方案2】:

    您应该将对象转换为 IEnumerable 或您知道的类型

      var collection = (PrincipalSearchResult<Principal>) e.Result;
      foreach (var PC in collection) 
        {
            comboBox1.Items.Add(PC.ToString());
        }     
    

    【讨论】:

    • 添加了 System.Collections,添加了您的建议,收到此错误。现在阅读有关 IEnumerable 的信息。 System.DirectoryServices.dll 中发生“System.InvalidCastException”类型的异常,但未在用户代码中处理附加信息:无法将“System.__ComObject”类型的 COM 对象转换为接口类型“IDirectorySearch”。此操作失败,因为 IID 为“{109BA8EC-92F0-11D0-A790-00C04FD8D5A8}”的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:不支持此类接口(来自 HRESULT 的异常:0x80004002 (E_NOINTERFACE)) .
    • 我不知道你为什么要添加System.Collections,它不需要演员......还有一个问题是PrincipalSearchResult是否实现了IEnumerable接口?
    • 我添加了它,希望它能改变一些东西哈哈。我阅读了更多关于 IEnum 的内容,如果我没看错,它是 Enumerable 的通用版本?无论如何,不​​,它没有实现 IEnum 接口。仍然收到 InvalidCast 异常。
    猜你喜欢
    • 2013-07-29
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多