【问题标题】:Stop / abort a class-loop thread, C#停止/中止一个类循环线程,C#
【发布时间】:2020-08-16 20:04:04
【问题描述】:

我已经在 c# 中启动了一个线程,但我希望能够中止它,但我真的不知道该怎么做。

private void createThread(){
     Thread threadDraw = new Thread(new ThreadStart(myMethod /*Starts a class which loops for a long time*/ ));
     threadDraw.Start();
     if(myBool == false) {theadDraw.Abort();}
}

myMethod 正在启动一个循环运行的类。问题是,我希望能够通过按键停止循环(在我的情况下)。目前,我已经尝试过

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    /* Checks space press, if space press: make myBool = false */
}

它将 myBool 更改为 false 并且该方法本身有效。

这里的问题是,createThread() 不会不断检查myBool 是否为假,因此不会停止。

我也试过

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    /*checks for spacepress, then {threadDraw.Abort()} */
}

但它也不起作用,我尝试在 createThread 上将 private 替换为 public,但仍然不起作用。

此外,我一直在考虑在类中创建一个 KeyDown()-method 并在循环中有一个 break; 但要么我做错了(可能),要么就是不可能。

【问题讨论】:

标签: c#


【解决方案1】:

您的代码if(myBool == false) {theadDraw.Abort();} 不起作用,因为您在线程启动后立即检查了一次。而且它再也不会被检查(threadDate.Start()' 不是阻塞调用)。

但是,NET Framework 包含CancellationToken 概念,用于取消异步代码。

// Step 1, create a cancellation token:
CancellationTokenSource cancel = new CancellationTokenSource();

// Step 2, reference the token from inside your thread
void ThreadStartMethod() {
   while (!cancel.IsCancellationRequested) {
      // Do work ...
   }
}

// Step 3, cancel the token when you need to
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Space)
       cancel.Cancel();
}

注意:确保在启动线程时重新创建取消令牌

【讨论】:

  • 我最近尝试使用取消令牌,但由于循环在类内部,它当时不起作用。虽然我现在已经将循环移到了课堂之外,因此我现在可以取消它。谢谢!
【解决方案2】:

我已尝试在 createThread 上将 private 替换为 public,但仍然无法正常工作。

这只会改变方法的可见性,而不是方法的工作。

一个线程只执行一次代码。很可能您的myMethod 有一个循环阻止它被终止。 Abort 终止线程的方式并不优雅(请参阅文档的 Remarks 部分)。您的代码中已经有一个条件变量myBool,您可以在myMethod 中使用它来优雅地退出循环并让线程自行终止。

void myMethod() {
    while (myBool && myLogic) { // if myBool is false, short-circuit and leave
        // thread code here.
    }
}

这将帮助线程通过退出循环知道何时停止。哦,这种方法需要您设置myBool 值的第一个Form1_KeyDown 方法。

请注意,您不需要使用while,也可以使用任何其他迭代结构,例如do...whilefor 循环。逻辑是一旦myBool 变为假就结束循环。是的,break 也可以。 :-)

现在,回到你的陈述:

我希望能够中止它

如果您希望立即中止威胁,那么我的方法将不起作用,因为它需要在循环执行之前进行条件检查。因此,您可能预计会有几微秒的延迟——如果您的业务需要微秒的精度,则需要使用 Abort 强制关闭线程。

【讨论】:

    猜你喜欢
    • 2018-01-04
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多