如何在WinForms C#中使用线程?
我有一个关于使用线程的问题。我有一个WinForms应用程序。我有一个带有方法的开始按钮。当我点击它时,该方法开始执行并持续很长时间。当该方法正在执行时,表单处于非活动状态,我甚至无法关闭它,直到该方法结束。我想激活表单并单击另一个按钮(停止按钮)停止方法的执行如何在WinForms C#中使用线程?,c#,multithreading,winforms,C#,Multithreading,Winforms,我有一个关于使用线程的问题。我有一个WinForms应用程序。我有一个带有方法的开始按钮。当我点击它时,该方法开始执行并持续很长时间。当该方法正在执行时,表单处于非活动状态,我甚至无法关闭它,直到该方法结束。我想激活表单并单击另一个按钮(停止按钮)停止方法的执行 private void start_Click(object sender, EventArgs e) { StartLoading() //Some Method which performing I
private void start_Click(object sender, EventArgs e)
{
StartLoading() //Some Method which performing I want to stop at any time
}
private void stop_Click(object sender, EventArgs e)
{
//Stop performing Method from start_Click
}
我尝试使用下一个代码:
private void start_Click(object sender, EventArgs e)
{
Thread StartThread = new Thread(StartLoading);
StartThread.Start();
}
public void StartLoading()
{
}
它是有效的。当窗体保持活动状态时,该方法正在执行。但我不知道如何在stop_Click事件中停止此线程。
也许还有别的方法可以做我想做的事
致意
Sergey如果您在线程内执行一些循环,我建议您添加一个变量,如下所示:
Thread StartThread = null;
private void start_Click(object sender, EventArgs e)
{
StartThread = new Thread(StartLoading);
StartThread.Start();
}
public void StartLoading()
{
StartThread.Abort();
}
在“停止”按钮中,添加以下内容:
bool isStopped = false;
在你的循环中:
while(yourCondition)
{
if(isStopped)
break;
}
这样,它更安全,可以确保您完成当前循环
但是如果你想立即终止它,有一个函数叫做
您必须修改如下代码:
Thread StartThread = null;
private void start_Click(object sender, EventArgs e)
{
StartThread = new Thread(StartLoading);
StartThread.Start();
}
public void StartLoading()
{
StartThread.Abort();
}
如果希望执行缓慢的操作直到完成或手动取消它,则可能需要使用
Task
和CancellationToken
。对我来说,这似乎是最合适的方式:
public class MyForm
{
private CancellationTokenSource cts = new CancellationTokenSource();
private Task task;
private void buttonStart_Click(object sender, EventArgs e)
{
buttonStart.Enabled = false;
buttonCancel.Enabled = true;
task = Task.Factory.StartNew(() => {
// do something extremely slow
// and use 'ThrowIfCancellationRequested'
for (int i = 0; i < Int32.MaxValue; i++)
{
Thread.Sleep(10);
cts.Token.ThrowIfCancellationRequested();
}
}, cts.Token).ContinueWith(t => {
if (t.IsCanceled)
{
// User has cancelled loading
}
if (t.IsFaulted)
{
// Exception has occured during loading
}
if (t.IsCompleted)
{
// Loading complete
}
});
}
private void buttonCancel_Click(object sender, EventArgs e)
{
buttonStart.Enabled = true;
buttonCancel.Enabled = false;
cts.Cancel();
}
}
公共类MyForm
{
私有CancellationTokenSource cts=新的CancellationTokenSource();
私人任务;
私有无效按钮开始单击(对象发送者,事件参数e)
{
buttonStart.Enabled=false;
按钮取消启用=真;
task=task.Factory.StartNew(()=>{
//做一些非常慢的事情
//并使用“ThrowIfCancellationRequested”
对于(inti=0;i{
如果(t.IsCanceled)
{
//用户已取消加载
}
如果(t.IsFaulted)
{
//加载期间发生异常
}
如果(t.已完成)
{
//装载完成
}
});
}
私有无效按钮取消单击(对象发送者,事件参数e)
{
buttonStart.Enabled=true;
按钮取消启用=错误;
cts.Cancel();
}
}
您可以为此使用后台工作人员
private BackgroundWorker bw = new BackgroundWorker();
public Form()
{
InitializeComponent();
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
private void start_Click(object sender, EventArgs e)
{
if (!bw.IsBusy)
{
bw.RunWorkerAsync();
}
}
private void stop_Click(object sender, EventArgs e)
{
if (bw.WorkerSupportsCancellation)
{
bw.CancelAsync();
}
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
StartLoading(); //Some Method which performing I want to stop at any time
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
//"Canceled!";
}
else if (e.Error != null)
{
//"Error: " + e.Error.Message);
}
else
{
//"Done!";
}
}
请注意,调用StartThread.Abort()
将引发异常,应捕获该异常。谢谢。你的答案有效。这很简单。所有其他答案对我来说都太难理解了。)@SergeyThread.Abort()
,它会让你的程序处于损坏状态。不要这样做。是的,所以我提出了一个解决办法,并告诉op如果他真的需要立即终止线程,那么就使用这个方法。我认为thread.Abort()对我来说很好。因为我很少使用它,而且只有在出现问题并且我想立即停止程序时,我才考虑它的可操作性。谢谢StartThread.Abort();我认为您需要使用cts.Token.ThrowIfCancellationRequested()
而不是if(cts.IsCancellationRequested)返回如果希望t.IsCanceled
在任务启动后取消,则返回true。如果您不认为任务认为取消是请求的,但方法完成了它的工作,因此它将其标记为IsCompleted
@ScottChamberlain当然,您是对的。我已经编辑了我的答案。我是否缺少尝试。。在某个地方捕获
,或者它会正确处理操作取消异常
本身吗?谢谢。如果OperationCanceledException与作为第二个参数传递给StartNew
的同一个令牌相关联,它将被视为特例,并进入IsCanceled状态,而不是IsFaulted状态。如果引发OperationCanceledException,但它未与传入的令牌关联,则它将显示为故障任务。有关详细示例,请参阅MSDN页“”。