2013-09-09 3 views
2

У меня есть подпрограмма GetEmployeeList, которая загружается при запуске приложения Windows.Лучшая техника: Чтение данных в потоке

Эта процедура вытаскивает основную информацию о сотруднике с нашего сервера Active Directory и сохраняет это в списке под названием m_adEmpList.

У нас есть несколько учетных записей Windows, созданных как Публичные профили, что большинство наших сотрудников используют наши производственные помещения. Это m_adEmpList дает нашим сотрудникам возможность входа в систему, чтобы выбрать функции, используя те Public Profiles.

После того как все Active Directory данных загружается, я попытка «автоматического входа в систему», что сотрудник на основе System.Environment.UserName, если это лицо регистрируется в соответствии с их частным профилем. (сотрудники любят это, между прочим)

Если я не прокручиваю GetEmployeeList, форма Windows будет отображаться не реагировать до завершения процедуры.

Проблема GetEmployeeList в том, что у нас были времена, когда сервер Active Directory была вниз, сеть была вниз, или конкретный компьютер не может подключиться через нашу сеть.

Чтобы обойти эти проблемы, я включил ManualResetEventm_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; 
} 

Я хотел бы просто поставить основные lock используя что-то вроде m_adEmpList, но я не уверен, что это хорошая идея, чтобы зафиксировать то, что мне нужно заполнить, а фактическое население данных собирается происходят в другом потоке, используя процедуру fillThread.

Если WaitOne по таймеру ManualResetEvent «s не удается собрать данные, мне нужно в отведенное время, то, вероятно, проблема сети, и m_mre не имеет много записей (если таковые имеются). Поэтому в следующий раз мне нужно будет снова попытаться извлечь эту информацию.

Если кто-то понимает, что я пытаюсь объяснить, я бы хотел, чтобы это было лучше.

Это просто кажется слишком вынужденным, прямо сейчас. Я продолжаю думать, что есть лучший способ сделать это.

ответ

1

Я думаю, что вы собираетесь использовать многопоточную часть неправильно. Я не могу это объяснить, но потоки должны сотрудничать и не конкурировать за ресурсы, но это именно то, что вас немного беспокоит. Другая проблема заключается в том, что ваш тайм-аут слишком длинный (так что он раздражает пользователей) и в то же время слишком короткий (если сервер AD немного медленный, но все еще там и обслуживает). Ваша цель должна состоять в том, чтобы поток выполнялся в фоновом режиме, и когда он закончен, он обновляет список. В то же время вы предоставляете пользователю некоторые резервные копии и уведомление о том, что список пользователей по-прежнему заполняется.

Несколько дополнительных примечаний на код выше:

  • У вас есть переменная m_thread, которая используется только локально. Кроме того, ваш код содержит избыточную проверку, является ли эта переменная нулевой.
  • Если вы сначала создаете список пользователей по умолчанию/резервные копии, а затем обновляете его через функцию (убедитесь, что вы проверяете флаг InvokeRequired элемента управления отображением!) Вам не понадобится блокировка. Это означает, что нить не имеет доступа к списку, хранящемуся как член, а к отдельному списку, к которому он имеет эксклюзивный доступ (не переменную-член). Затем функция обновления заменяет (!) Этот список, поэтому теперь он используется исключительно для пользовательского интерфейса.
  • Наконец, если сервер AD на самом деле не существует, попробуйте каким-либо образом переслать ошибку из фонового потока в пользовательский интерфейс, чтобы пользователь знал, что сломано.
  • Если вы хотите, вы можете добавить событие, чтобы сигнализировать о прекращении потока, но в большинстве случаев это даже не понадобится.
Смежные вопросы