Как бы я заполнил ListBox от backgroundworker? - PullRequest
1 голос
/ 29 октября 2019

У меня проблемы с заполнением списка из цепочки фонов. В настоящее время у меня есть следующий код:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        var lockedUsers = new List<UserPrincipal>();
        using (var context = new PrincipalContext(ContextType.Domain, "domain", smtu, smtp))
        {
            GroupPrincipal grp = GroupPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "Domain Users");
            foreach (var userPrincipal in grp.GetMembers(false))
            {

                var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userPrincipal.SamAccountName);
                if (user != null)
                {
                    if (user.IsAccountLockedOut())
                    {
                        listBox1.Items.Add(@"domain\ " + user);
                    }
                }
            }
        }
    }

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

    List<string> listusers = new List<string>();


    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        var lockedUsers = new List<UserPrincipal>();
        using (var context = new PrincipalContext(ContextType.Domain, "domain", smtu, smtp))
        {
            GroupPrincipal grp = GroupPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "Domain Users");
            foreach (var userPrincipal in grp.GetMembers(false))
            {

                var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userPrincipal.SamAccountName);
                if (user != null)
                {
                    if (user.IsAccountLockedOut())
                    {
                        listusers.Add(@"domain\" + user);
                    }
                }
            }
        }
    }

    private async void timerlocked_Tick(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
        listBox1.DataSource = listusers;
    }

Есть идеи?

Ответы [ 2 ]

1 голос
/ 29 октября 2019

DoWorkEventArgs, который передается делегату DoWorkEventHandler, имеет свойство Result

Получает или задает значение, представляющее результат асинхронной операции.

Заданный вами Result будет отправлен вместе с событием RunWorkerCompleted через RunWorkerCompletedEventArgs, который будет передан этому делегату.

Итак, чтобы решить эту проблему, вы можете построить List<string> внутри события DoWork, установить свойство Result для этого списка, обработать событие RunWorkerCompleted и получить доступ к списку из RunWorkerCompletedEventArgs.Result.

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    var result = new List<string>();
    var lockedUsers = new List<UserPrincipal>();
    using (var context = new PrincipalContext(ContextType.Domain, "domain", smtu, smtp))
    {
        GroupPrincipal grp = GroupPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "Domain Users");
        foreach (var userPrincipal in grp.GetMembers(false))
        {

            var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userPrincipal.SamAccountName);
            if (user != null)
            {
                if (user.IsAccountLockedOut())
                {
                    result.Add(@"domain\ " + user);
                }
            }
        }
    }
    e.Result = result;
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        // Error handling.
    }
    if (e.Cancelled)
    {
       // If you support cancellation...
    }
    listBox1.Items.Clear();
    listBox1.Items.AddRange((e.Result as List<string>).ToArray());
}
0 голосов
/ 29 октября 2019

Чтобы получить доступ к потоку пользовательского интерфейса из фонового рабочего, вы можете выполнить свою работу в событии RunWorkerCompleted BackgroundWorker или - если вы хотите получить доступ к пользовательскому интерфейсу во время работы рабочего, посмотрите на Control.Invoke.

Позднее может выглядеть так:

if (user.IsAccountLockedOut())
{
    listBox1.Invoke(() => listBox1.Items.Add(@"domain\ " + user));
}
...