C# windows窗体C中的多线程处理#
在windows应用程序中,除了主线程外,还有一个线程每分钟执行一次长时间运行操作,并使用Invoke方法更新UI 当另一个线程处于睡眠状态时,我们如何优雅地终止它C# windows窗体C中的多线程处理#,c#,.net,winforms,C#,.net,Winforms,在windows应用程序中,除了主线程外,还有一个线程每分钟执行一次长时间运行操作,并使用Invoke方法更新UI 当另一个线程处于睡眠状态时,我们如何优雅地终止它 在这里使用sleep是正确的选择吗?与其让线程运行一次然后终止,不如使用窗体计时器每隔60000毫秒触发一个后台工作线程?然后,您根本不需要休眠背景线程 这意味着您只需要停止计时器来停止生成更多的后台任务,但显然这不会停止任何当前活动的后台线程 线程应该很少被中止,因为没有任何好的机制可以以任何一致性进行中止。有各种保护措施,如关键
在这里使用sleep是正确的选择吗?与其让线程运行一次然后终止,不如使用窗体计时器每隔60000毫秒触发一个后台工作线程?然后,您根本不需要休眠背景线程 这意味着您只需要停止计时器来停止生成更多的后台任务,但显然这不会停止任何当前活动的后台线程 线程应该很少被中止,因为没有任何好的机制可以以任何一致性进行中止。有各种保护措施,如关键代码标记。然而,我认为最好是对取消进行长时间运行的代码轮询,然后您可以编写自己的逻辑,以便弃船并提前返回注意,这与强制中止线程不同 我不认为在任何情况下睡觉都是正确的选择 例如:
private bool _askedToCancel;
public void lonRunThread()
{
if (!_askedToCancel)
{
Operation1();
Invoke(new UpdateDelegate(updateState));
}
if (!_askedToCancel)
{
Operation2();
Invoke(new UpdateDelegate(updateState));
}
}
看起来有点混乱,但是如果拒绝强制中止线程,而是使用取消方法,则可以很好地控制执行什么逻辑
因为这不是关键代码,而且布尔操作是原子的,所以让两个线程在没有任何锁定的情况下与布尔对话应该是安全的。即使它不是真正安全的,唯一的结果就是做了更多的工作。不是让线程运行一次然后终止,而是使用窗体计时器每60000毫秒触发一个后台工作线程?然后,您根本不需要休眠背景线程 这意味着您只需要停止计时器来停止生成更多的后台任务,但显然这不会停止任何当前活动的后台线程 线程应该很少被中止,因为没有任何好的机制可以以任何一致性进行中止。有各种保护措施,如关键代码标记。然而,我认为最好是对取消进行长时间运行的代码轮询,然后您可以编写自己的逻辑,以便弃船并提前返回注意,这与强制中止线程不同 我不认为在任何情况下睡觉都是正确的选择 例如:
private bool _askedToCancel;
public void lonRunThread()
{
if (!_askedToCancel)
{
Operation1();
Invoke(new UpdateDelegate(updateState));
}
if (!_askedToCancel)
{
Operation2();
Invoke(new UpdateDelegate(updateState));
}
}
看起来有点混乱,但是如果拒绝强制中止线程,而是使用取消方法,则可以很好地控制执行什么逻辑
因为这不是关键代码,而且布尔操作是原子的,所以让两个线程在没有任何锁定的情况下与布尔对话应该是安全的。即使它不是真正安全的,唯一的结果就是做了更多的工作。您可以始终将线程设置为后台线程,这样当应用程序退出时,线程将自动停止 您希望线程何时停止 如果希望在操作中间停止,则布尔标志将是合适的 所以不是
while(true)
你会这样做
while(exit == false)
您可以始终将线程设置为后台线程,这样当应用程序退出时,线程将自动停止 您希望线程何时停止 如果希望在操作中间停止,则布尔标志将是合适的 所以不是
while(true)
你会这样做
while(exit == false)
我将更改longRunThread方法中的while(true)并使其
while (_RunLongThread)
然后,在TestForm中,我将声明私有布尔值_RunLongThread=true,并将其设置为false,无论哪个方法需要停止长时间运行的线程
这是一种“优雅”的停止方式,即等待完成其当前任务,然后终止我将更改longRunThread方法中的while(true)并使其生效
while (_RunLongThread)
然后,在TestForm中,我将声明私有布尔值_RunLongThread=true,并将其设置为false,无论哪个方法需要停止长时间运行的线程
这是一种“优雅”的停止方式,即等待完成当前任务,然后终止没有优雅的线程终止。相反,当不再需要线程时,应该指示线程停止它的工作。您可以通过创建一个类来保存工作线程参数,在该类中存储是否应该停止工作的信息,并将该类的对象传递给线程
public class WorkerParams
{
public bool Stop = false;
}
private void TestForm_Load(object sender, EventArgs e)
{
_thread = new Thread(lonRunThread);
_thread.Start(new WorkerParams());
}
public void lonRunThread(object argument)
{
WorkerParams param = argument as WorkerParams;
DateTime lastExec = DateTime.MinValue;
while(!param.Stop)
{
if (new TimeSpan(DateTime.Now.Ticks - lastExec.Ticks).TotalSeconds >= 60)
{
Operation1();
Invoke(new UpdateDelegate(updateState));
Operation2();
Invoke(new UpdateDelegate(updateState));
lastExec = DateTime.Now;
}
Thread.Sleep(500);
}
}
没有优雅的线程终止。相反,当不再需要线程时,应该指示线程停止它的工作。您可以通过创建一个类来保存工作线程参数,在该类中存储是否应该停止工作的信息,并将该类的对象传递给线程
public class WorkerParams
{
public bool Stop = false;
}
private void TestForm_Load(object sender, EventArgs e)
{
_thread = new Thread(lonRunThread);
_thread.Start(new WorkerParams());
}
public void lonRunThread(object argument)
{
WorkerParams param = argument as WorkerParams;
DateTime lastExec = DateTime.MinValue;
while(!param.Stop)
{
if (new TimeSpan(DateTime.Now.Ticks - lastExec.Ticks).TotalSeconds >= 60)
{
Operation1();
Invoke(new UpdateDelegate(updateState));
Operation2();
Invoke(new UpdateDelegate(updateState));
lastExec = DateTime.Now;
}
Thread.Sleep(500);
}
}
那么,上述方法会让最终用户等待,然后您将需要更复杂的处理。使用1000ms睡眠,并计算自上次执行以来是否经过了足够的时间。好的,上述方法会让最终用户等待,然后您将需要更复杂的处理。执行1000ms睡眠,并计算自上次执行以来是否经过了足够的时间。实际上,OPeration1()和OPeration2()有一些非托管代码。如果在处理OPeration1()或OPeration2()时线程突然终止,则会导致内存泄漏。另一方面,您必须在非托管代码中使用指针吗?我理解这一点。我的问题是,你能不使用指针就离开吗?例如,你没有C=新的C();但是,您可以编写它,以便在函数超出范围时自动销毁对象,即C;c、 长_操作();不目前,由于内存不足,当对象超出范围时,无法自动销毁该对象