2

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

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

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

加载所有Active Directory数据后,我会尝试根据该员工System.Environment.UserName是否在其私人配置文件下登录来“自动登录”该员工。(顺便说一句,员工喜欢这个)

如果我不使用线程GetEmployeeList,Windows 窗体将显示为无响应,直到例程完成。

问题GetEmployeeList在于,我们有时会遇到Active Directory服务器关闭、网络关闭或特定计算机无法通过我们的网络连接的情况。

为了解决这些问题,我在超时中包含了一个ManualResetEvent m_mreTHREADSEARCH_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,但我不确定锁定我需要填充的东西是否是个好主意,并且实际的数据填充将使用例程在另一个线程中发生fillThread

如果ManualResetEventWaitOne计时器未能在分配的时间内收集到我需要的数据,则可能是网络问题,并且m_mre没有很多记录(如果有的话)。因此,我下次需要尝试再次提取此信息。

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

只是现在看来太勉强了。我一直在想有更好的方法来做到这一点。

4

1 回答 1

1

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

关于上面代码的更多注释:

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