我在我的计划中遇到了麻烦。该程序是一个登录检查器,它读取用户列表和&密码然后它1对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();
}
}
答案 0 :(得分:2)
首先,我想告诉你为什么你会遇到这样的问题。
你正在做一个沉重的&#39;在主线程(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获得。
BTW ,如果您使用上述解决方案,请记得使用 Form.Invoke()访问表单上的控件,或设置 Control.CheckForIllegalCrossThreadCalls 为假。
答案 1 :(得分:0)
这是因为它在UI线程上运行。如果您使用的是.net&gt; = 4.5,请尝试使用Task.Run()
此外,您可以使用取消令牌来停止登录过程
答案 2 :(得分:0)
嗯,这只是一个线程问题。 You Login方法在默认线程上运行,该线程是UI使用的线程。因此,当您的代码使用此线程尝试登录时,UI上的操作执行被阻止,因为线程正忙。
您需要做的是让您的登录在另一个线程上运行,这样它就不会阻止UI线程。这可以使用不同的方法完成,例如Tasks或Backgroundworker。这两个都支持取消,这意味着可以触发它们停止当前的操作。