用户退出循环(取消按钮)
Exit for loop by user (cancel button)
我的程序遇到了问题。该程序是一个登录检查器,它读取用户和密码列表,然后逐一测试登录。
我面临的问题是,当我列出一长串程序时,程序需要一段时间,因此需要取消按钮或暂停。当该循环(登录测试)中的程序 运行 时,window 表单冻结,我无法按任何按钮,甚至无法对其进行麻醉。
这是循环:
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();
}
}
发生这种情况是因为它在 UI 线程上 运行。如果您使用的是 .net >=4.5,请尝试使用 Task.Run()
此外,您可以使用取消令牌来停止登录过程
好吧,这只是一个线程问题。您的登录方法是 运行ning 在默认线程上,这是 UI 使用的线程。因此,当您的代码使用此线程尝试登录时,UI 上的操作的执行被阻止,因为线程正忙。
您需要做的是让您的登录 运行 在另一个线程上,这样它就不会阻塞 UI 线程。这可以使用不同的方法来完成,例如 Tasks or Backgroundworker。这两者都支持取消,这意味着可以触发它们停止当前操作。
首先我想告诉你为什么你会遇到这样的问题。
您正在主线程(UI 线程)中执行 'heavy' 操作,当该线程忙于处理任务(检查用户和密码)时,它不会响应 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
与方案一类似,只是将用户创建的后台线程替换为System.ComponentModel.BackgroundWorker,关于如何使用BackgroundWorker,请参见https://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker.aspx了解更多信息.
解决方案 3 使用线程池
使用 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 设置为 false.
我的程序遇到了问题。该程序是一个登录检查器,它读取用户和密码列表,然后逐一测试登录。 我面临的问题是,当我列出一长串程序时,程序需要一段时间,因此需要取消按钮或暂停。当该循环(登录测试)中的程序 运行 时,window 表单冻结,我无法按任何按钮,甚至无法对其进行麻醉。 这是循环:
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();
}
}
发生这种情况是因为它在 UI 线程上 运行。如果您使用的是 .net >=4.5,请尝试使用 Task.Run()
此外,您可以使用取消令牌来停止登录过程
好吧,这只是一个线程问题。您的登录方法是 运行ning 在默认线程上,这是 UI 使用的线程。因此,当您的代码使用此线程尝试登录时,UI 上的操作的执行被阻止,因为线程正忙。
您需要做的是让您的登录 运行 在另一个线程上,这样它就不会阻塞 UI 线程。这可以使用不同的方法来完成,例如 Tasks or Backgroundworker。这两者都支持取消,这意味着可以触发它们停止当前操作。
首先我想告诉你为什么你会遇到这样的问题。
您正在主线程(UI 线程)中执行 'heavy' 操作,当该线程忙于处理任务(检查用户和密码)时,它不会响应 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
与方案一类似,只是将用户创建的后台线程替换为System.ComponentModel.BackgroundWorker,关于如何使用BackgroundWorker,请参见https://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker.aspx了解更多信息.
解决方案 3 使用线程池
使用 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 设置为 false.