C#在foreach循环期间暂停,直到Process.Exited

时间:2015-08-13 16:17:42

标签: c# process

所以我有一个遍历DataGridView的foreach循环。对于网格中的每一行,它执行pspasswrd.exe并更改本地帐户的密码。在进入列表中的下一台计算机之前,如何暂停foreach循环直到进程完成?

我不确定,我尝试了WaitForExit,但这不可靠,因为它是同步的,所以如果需要很长时间,它会导致程序无法响应。我需要利用Process.Exited但不确定如何正确地执行此操作。

这是我的foreach循环。这也检查密码是否成功更改。如果成功,则将数据输入另一个Datagridview。

foreach (DataGridViewRow row in dgvData.Rows)
        {
            if (!row.IsNewRow && row.Cells["cIPAddress"].Value.ToString().Contains("Invalid") == false)
            {
                if (pspasswrd(row.Cells["cIPAddress"].Value.ToString(), tbTargetUser.Text, NewPassword).Contains("Password successfully changed"))
                {
                    dgvResults.Rows.Add(row.Cells["cIPAddress"].Value.ToString(), tbTargetUser.Text, NewPassword);
                    AppendNumber = AppendNumber + IncreaseNumber;
                    NewPassword = BasePassword + AppendNumber;
                }
                else
                    row.DefaultCellStyle.BackColor = Color.Red;
            }
            Thread.Sleep(1000);
        }

但我不确定的是,如果我将下面的代码更改为使用process.exited。它如何将密码更改与其成功运行的计算机相关联。因为它将是异步的。

public string pspasswrd(string ip, string user, string password)
    {
        String CD = @Directory.GetCurrentDirectory() + "\\pspasswrd.exe";
        ProcessStartInfo p = new ProcessStartInfo();
        string result = null;
        p.FileName = CD;
        p.Arguments = @"\\" + ip + " " + user + " " + password + " -accepteula";
        p.CreateNoWindow = true;
        p.RedirectStandardOutput = true;
        p.RedirectStandardError = true;
        p.UseShellExecute = false;
        Process x = Process.Start(p);
        StreamReader stream = x.StandardOutput;
        result = stream.ReadToEnd();
        x.WaitForExit(2000);
        x.Close();
        return result;
    }

1 个答案:

答案 0 :(得分:1)

您应首先从集合中的DataGridView收集所有需要的信息,然后运行您的代码,在循环集合而不是DataGridView的后台线程中执行pspasswrd.exe并使用WaitForExit,这不会阻止您的UI线程。

修改

以下是WaitForExit和新线程的代码。我相信你不会使用Exit事件而不是WaitForExit获得更多,除了更多的复杂性和死锁场景:

 private void OnSomeUIEvent()
    {
        //In UI thread
        var ipRows = new Dictionary<string, DataGridViewRow>();
        var targetUser = ""; //tbTargetUser.Text
        var pwd = ""; //NewPassword
        var basePassword = ""; //Some value

        foreach (DataGridViewRow row in dgvData.Rows)
        {
            var ipAddress = row.Cells["cIPAddress"].Value.ToString();

            if (!row.IsNewRow && ipAddress.Contains("Invalid") == false)
            {
                ipRows.Add(ipAddress, row);
            }
        }

        Task.Factory.StartNew(() => {

            ChangePassword(ipRows, targetUser, pwd, basePassword);

        }).ContinueWith(t => { 

           //Do Something when task completed

        });
    }

    private void ChangePassword(Dictionary<string, DataGridViewRow> ipRows, string targetUser, string newPwd, string basePwd)
    {  //in background thread
        foreach (var ipRow in ipRows)
        {
            var pwd = newPwd;
            var basePassword = basePwd;
            var appendNumber = 0;
            var increaseNumber = 1; //some number

            if (pspasswrd(ipRow.Key, targetUser, pwd).Contains("Password successfully changed"))
            {
                dgvResults.Invoke((MethodInvoker)(() =>
                {
                    dgvResults.Rows.Add(ipRow.Key, targetUser, pwd);
                }));

                appendNumber = appendNumber + increaseNumber;
                pwd = basePassword + increaseNumber;
            }
            else
            {
                dgvData.Invoke((MethodInvoker)(() =>
                {
                    ipRow.Value.DefaultCellStyle.BackColor = Color.Red;
                }));
            }
        }
    }