C# 停止线程的最佳方法

C# 停止线程的最佳方法,c#,multithreading,C#,Multithreading,我正在使用线程池中的线程执行一些操作。 现在,在某些情况下,如果出现问题,我想关闭表单。 我有一个try/catch块,如果它捕捉到了什么,它应该做些什么,然后关闭表单。问题是,当关闭时,线程在后台继续运行,然后在调用某个对象的位置抛出异常,因为句柄不再存在 我需要停止线程,这样它就不会继续了。我听说“Abort”不是一个好的解决方案,我应该创建一个标志变量并进行查询,但我应该如何做到这一点? 有没有更好的办法? 如果您需要代码,请告诉我,但这是一个更一般的问题 谢谢 我不确定问题出在哪里,因为

我正在使用线程池中的线程执行一些操作。 现在,在某些情况下,如果出现问题,我想关闭表单。 我有一个try/catch块,如果它捕捉到了什么,它应该做些什么,然后关闭表单。问题是,当关闭时,线程在后台继续运行,然后在调用某个对象的位置抛出异常,因为句柄不再存在

我需要停止线程,这样它就不会继续了。我听说“Abort”不是一个好的解决方案,我应该创建一个标志变量并进行查询,但我应该如何做到这一点? 有没有更好的办法? 如果您需要代码,请告诉我,但这是一个更一般的问题


谢谢

我不确定问题出在哪里,因为您没有提供代码,但也许您应该检查InvokeRequired属性,请尝试以下操作:

if (Control.InvokeRequired)
{
// your code
}

我不确定问题出在哪里,因为您没有提供代码,但也许您应该检查InvokeRequired属性,请尝试以下操作:

if (Control.InvokeRequired)
{
// your code
}

我通常有一个标志,当窗体关闭时,或者当我需要线程因任何其他原因终止时,该标志被设置为true

另一个有用的方法是将
IsBackground
属性设置为
true
,这会使进程在最后一个窗体关闭时终止,而不是让幻影进程继续运行

例如,如果您有一个生成线程的窗体,该线程在
while(true)
中定期执行计算,则必须在窗体关闭时以某种方式手动终止该线程。如果设置了
IsBackground=true
,则线程不会阻止进程终止


(当然,您还应该记住,如果线程以某种方式与表单交互,那么您需要处理该问题,否则关闭表单可能会导致线程在无法访问已处理对象时出现异常,等等)。

我通常有一个标志,当表单关闭时,该标志会设置为true,或者当我需要线程因任何其他原因终止时

另一个有用的方法是将
IsBackground
属性设置为
true
,这会使进程在最后一个窗体关闭时终止,而不是让幻影进程继续运行

例如,如果您有一个生成线程的窗体,该线程在
while(true)
中定期执行计算,则必须在窗体关闭时以某种方式手动终止该线程。如果设置了
IsBackground=true
,则线程不会阻止进程终止


(当然,您还应该记住,如果线程以某种方式与窗体交互,那么您需要处理该问题,否则关闭窗体可能会导致线程中出现异常,当它不再能够访问已处理的对象时,等等)。

您必须确保线程正确地执行到最后并保持干净。在此之后,您可以关闭窗体并删除线程对象

这就是我通常处理所有线程的方式。我使用一组“信号”变量(我在自己的类中定义)来控制线程,并从应用程序线程检查其状态。如果你想抓住什么,那太棒了!只需通过完全退出“中止”功能,直到其空闲运行。线程完成后,您可以安全地删除它

    void MyThreadFunction () {
      bThreadActive = true;

      while(!bThreadTerminate){
        bThreadIdle = false;  //thread is no longer idle.
        bThreadStart = false; //Reset this too 

        //Do all your thread stuff here.
          doSomething();

        while(!bThreadTerminate){
          //Stay here until we start or terminate
          bThreadIdle = true;

          if(bThreadStart)
            break;
        }
      }

      bThreadActive = false;
    }

    void doSomething(){
      //Anytime you go into a loop and if statements, check if it's been terminated.
      //When you set bThreadTerminate to true, exit the thread without any further calculations.
      //Any logical statement needs to also check if you want to terminate the thread.

      int iNum1 = 1;
      int iNum2 = 1;

      try {
        if(iNum1 == iNum2 && !bThreadTerminate){
        //Stuff to do.
        }
      }catch(Exception *e){
        //Abort Code here
      }
    }
因此,基本上,这将执行一次所有操作,并等待您需要再次执行(在您的通话中)。将bStart设置为true,它将一直循环,直到再次空闲。如果您将bThreadTerminate设置为true,那么在主线程上,您将等待bActive为false后再删除它


我希望这会有所帮助。

您必须确保线程正确、干净地执行到底。在此之后,您可以关闭窗体并删除线程对象

这就是我通常处理所有线程的方式。我使用一组“信号”变量(我在自己的类中定义)来控制线程,并从应用程序线程检查其状态。如果你想抓住什么,那太棒了!只需通过完全退出“中止”功能,直到其空闲运行。线程完成后,您可以安全地删除它

    void MyThreadFunction () {
      bThreadActive = true;

      while(!bThreadTerminate){
        bThreadIdle = false;  //thread is no longer idle.
        bThreadStart = false; //Reset this too 

        //Do all your thread stuff here.
          doSomething();

        while(!bThreadTerminate){
          //Stay here until we start or terminate
          bThreadIdle = true;

          if(bThreadStart)
            break;
        }
      }

      bThreadActive = false;
    }

    void doSomething(){
      //Anytime you go into a loop and if statements, check if it's been terminated.
      //When you set bThreadTerminate to true, exit the thread without any further calculations.
      //Any logical statement needs to also check if you want to terminate the thread.

      int iNum1 = 1;
      int iNum2 = 1;

      try {
        if(iNum1 == iNum2 && !bThreadTerminate){
        //Stuff to do.
        }
      }catch(Exception *e){
        //Abort Code here
      }
    }
因此,基本上,这将执行一次所有操作,并等待您需要再次执行(在您的通话中)。将bStart设置为true,它将一直循环,直到再次空闲。如果您将bThreadTerminate设置为true,那么在主线程上,您将等待bActive为false后再删除它


我希望这能有所帮助。

好吧,我设法做到了,任务其实很简单

必须声明一个CancellationTokenSource和一个操作,以便执行void/函数。 就像这样:

CancellationTokenSource cancellationToken = new CancellationTokenSource();
Action yourAction;
然后使用要执行的void初始化操作:

yourAction = anyvoid;
最后:

yourAction.BeginInvoke(yourAction.EndInvoke, null); 
你就是这样开始的。 现在,当您需要取消/停止线程时,您可以说:

cancellationToken.Cancel();
之后,它将取消线程。 为了避免线程在此期间运行,只需在所有“取消”执行之后进行查询

if (cancellationToken.IsCancellationRequested)
  return;

就这样。其优点是,您不必处理任何异常异常或任何事情,这是一种干净的停止线程的方法。

好吧,我成功地完成了,任务实际上非常简单

必须声明一个CancellationTokenSource和一个操作,以便执行void/函数。 就像这样:

CancellationTokenSource cancellationToken = new CancellationTokenSource();
Action yourAction;
然后使用要执行的void初始化操作:

yourAction = anyvoid;
最后:

yourAction.BeginInvoke(yourAction.EndInvoke, null); 
你就是这样开始的。 现在,当您需要取消/停止线程时,您可以说:

cancellationToken.Cancel();
之后,它将取消线程。 为了避免线程在此期间运行,只需在所有“取消”执行之后进行查询

if (cancellationToken.IsCancellationRequested)
  return;
就这样。优点是,您不必处理任何AbortException或任何事情,这是一种干净的停止线程的方法。

在Msdn上搜索“取消”