更好的技术:读取线程中的数据

时间:2013-09-09 20:33:58

标签: c# multithreading winforms networking active-directory

我有一个名为GetEmployeeList的例程,在我的Windows应用程序启动时加载。

此例程从我们的 Active Directory 服务器中提取基本员工信息,并将其保留在名为m_adEmpList的列表中。

我们有一些Windows帐户设置为公共配置文件,我们制造车间的大多数员工都使用这些帐户。此m_adEmpList使我们的员工能够使用公共配置文件登录以选择功能。

加载完所有 Active Directory 数据后,如果该用户在其私人资料下登录,我会尝试根据System.Environment.UserName“自动登录”该员工。 (顺便说一下,员工喜欢这个)

如果我没有线程GetEmployeeList,Windows窗体将无法响应,直到例程完成。

GetEmployeeList的问题在于,我们曾经有过 Active Directory 服务器关闭,网络关闭或某台计算机无法通过我们的网络连接的时间。

为了解决这些问题,我添加了ManualResetEvent m_mre THREADSEARCH_TIMELIMIT超时,以便该过程不会永远消失。在我拥有员工名单之前,我无法使用私人资料System.Environment.UserName登录某人。

我意识到我没有显示所有代码,但希望没有必要。

public static ADUserList GetEmployeeList()
{
  if ((m_adEmpList == null) ||
      (((m_adEmpList.Count < 10) || !m_gotData) &&
       ((m_thread == null) || !m_thread.IsAlive))
     )
  {
    m_adEmpList = new ADUserList();
    m_thread = new Thread(new ThreadStart(fillThread));
    m_mre = new ManualResetEvent(false);
    m_thread.IsBackground = true;
    m_thread.Name = FILLTHREADNAME;
    try {
      m_thread.Start();
      m_gotData = m_mre.WaitOne(THREADSEARCH_TIMELIMIT * 1000);
    } catch (Exception err) {
      Global.LogError(_CODEFILE + "GetEmployeeList", err);
    } finally {
      if ((m_thread != null) && (m_thread.IsAlive)) {
        // m_thread.Abort();
        m_thread = null;
      }
    }
  }
  return m_adEmpList;
}

我想使用像m_adEmpList这样的基本lock,但我不确定锁定我需要填充的内容以及实际数据是否是一个好主意使用例程fillThread将在另一个线程中发生填充。

如果ManualResetEventWaitOne计时器无法在分配的时间内收集我需要的数据,则可能存在网络问题,m_mre没有多条记录(如果任何)。所以,我需要在下次再尝试提取这些信息。

如果有人理解我要解释的内容,我希望看到更好的方法。

现在看起来太强迫了。我一直在想有更好的方法。

1 个答案:

答案 0 :(得分:1)

我认为你以错误的方式处理多线程部分。我无法解释它,但线程应该合作而不是争夺资源,但这正是困扰你的一点。另一个问题是你的超时时间太长(这会让用户烦恼)同时太短(如果AD服务器有点慢,但仍然在那里并且服务)。你的目标应该是让线程在后台运行,当它完成时,它会更新列表。在此期间,您会向用户提供一些回退以及用户列表仍在填充的通知。

上面代码中的一些注释:

  • 您有一个仅在本地使用的变量m_thread。此外,您的代码包含冗余检查该变量是否为空。
  • 如果您先创建一个带有默认值/回退的用户列表,然后通过一个函数更新它(确保您正在检查显示控件的InvokeRequired标志!),您将不需要锁定。这意味着线程不会访问作为成员存储的列表,而是访问它具有独占访问权限的单独列表(不是成员变量)。然后更新函数替换(!)此列表,因此现在它由UI独占使用。
  • 最后,如果AD服务器确实不在那里,请尝试以某种方式将错误从后台线程转发到UI,以便用户知道什么坏了。
  • 如果需要,可以添加一个事件来表示线程停止,但在大多数情况下甚至不需要。
相关问题