1

我的程序遇到了麻烦。该程序是一个登录检查器,它读取用户和密码列表,然后逐个测试登录。我面临的问题是当我放一个长列表时,程序需要一段时间,所以它需要一个取消按钮或暂停. 当程序在该循环中运行(登录测试)时,窗口窗体冻结,我无法按下任何按钮,甚至无法将其毒化。这是循环:

private void button1_Click(object sender, EventArgs e)
{
    string spl = textBox5.Text;
    int lin = textBox4.Lines.Count();

    for (int i = 0; i < lin; i++)
    {
        string dick = textBox4.Lines[i];
        Convert.ToString(dick);
        string[] wordArray = dick.Split(':');

        textBox1.Text = (Convert.ToString(wordArray[0]));
        textBox2.Text = (Convert.ToString(wordArray[1]));
        login();
    }
}
4

3 回答 3

2

首先我想告诉你为什么你会遇到这样的问题。
您正在主线程(UI 线程)中执行“繁重”操作,并且当该线程忙于处理任务(检查用户和密码)时,它不会响应 UI 消息。也就是说,它不会检查消息队列是否为空,因此在操作结束之前它不会对您的点击进行任何操作。
其次,我想找到几种方法来解决它。
解决方案 1使用后台线程来完成工作

    using System.Threading;
    private void button1_Click(object sender, EventArgs e)
    {
        Thread thread = new Thread(() => {
            this.Invoke(new Action(() => {
                string spl = textBox5.Text;
                int lin = textBox4.Lines.Count();
                for (int i = 0; i < lin; i++) {
                    string dick = textBox4.Lines[i];
                    Convert.ToString(dick);
                    string[] wordArray = dick.Split(':');

                    textBox1.Text = (Convert.ToString(wordArray[0]));
                    textBox2.Text = (Convert.ToString(wordArray[1]));
                    login();
                }
            }));
        });
        thread.Start();
    }

通过这种方式,您的 UI 在您进行操作时会响应您。

方案2使用BackgroundWorker
与方案1类似,只需将用户创建的后台线程替换为System.ComponentModel.BackgroundWorker即可,BackgroundWorker 的使用方法见https://msdn.microsoft.com/zh-cn /library/system.componentmodel.backgroundworker.aspx了解更多信息。

解决方案 3使用 ThreadPool
使用 System.Threading.ThreadPool 创建后台线程为您工作。这样,您就不必自己管理线程。更多信息请参见https://msdn.microsoft.com/zh-cn/library/system.threading.threadpool(v=VS.80).aspx

解决方案 4使用任务
使用 System.Threading.Task 执行您的操作。请参阅 msdn:
https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task.aspx
注意:System.Threading.Task可从 .NET Framework 4.0 获得。

顺便说一句,如果您使用上述解决方案,请记住使用Form.Invoke()来访问您在表单上的控件,或者将Control.CheckForIllegalCrossThreadCalls设置为 false。

于 2015-08-12T14:31:46.847 回答
1

发生这种情况是因为它在 UI 线程上运行。如果您使用 .net >=4.5,请尝试使用Task.Run()

此外,您可以使用取消令牌来停止登录过程

于 2015-08-12T13:29:40.407 回答
0

嗯,这只是一个线程问题。You Login 方法在默认线程上运行,这是 UI 使用的线程。因此,当您的代码使用此线程尝试登录时,UI 上的操作执行被阻止,因为该线程很忙。

您需要做的是让您的登录在另一个线程上运行,这样它就不会阻塞 UI 线程。这可以使用不同的方法来完成,例如TasksBackgroundworker。这两个也支持取消,这意味着可以触发它们停止执行当前操作。

于 2015-08-12T13:36:46.007 回答