【问题标题】:Thread.Join forcefully closes thread on application endThread.Join 强制关闭应用程序端的线程
【发布时间】:2016-05-30 23:10:17
【问题描述】:

我有一个实现 IDisposable 的类。该类包含一个线程,该线程在 Dispose 方法中使用Thread.Join(...)关闭

然而,我的问题是,如果我这样运行我的课程:

static void Main(string[] args)
{
    var class = new MyClass();
    class.Run();
}

当应用程序关闭时,它会强制关闭线程而不等待它完成执行。

但是,如果我这样运行它:

static void Main(string[] args)
{
    using (var class = new MyClass())
    {
        class.Run();
    }
}

线程完成它开始的工作并优雅地结束。允许线程完成执行的 using 语句是什么?

我的预感是使用第一种方法,因为应用程序已经退出,它会强制关闭线程而不等待它完成。但是,在 using 块下,应用程序仍在运行,因此有时间关闭线程然后退出应用程序。

如果我的预感是正确的,您能否告诉我为什么应用程序不等待线程在关闭之前完成?

编辑:

~ElasticBase()
{
    Dispose(false);
} 

public virtual void Initialize()
{
    workerThread = new Thread(ProcessData)
    {
        Name = "ElasticBase thread",
        IsBackground = true
    };

    IsInitialized = true;
}

public virtual void Shutdown()
{
    if (workerThread.IsAlive)
    {
        IsInitialized = false;
        lock (syncObject)
        {
            if (!workerThread.Join(10000))
            {
                workerThread.Abort();
            }
            workerThread = null;
        }
    }
}

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected void Dispose(bool calledFromDispose)
{
    Shutdown();
}

正如您在上面的代码中看到的那样。在 Dispose 中调用 Shutdown 方法。如果我不显式调用 Dispose 并且不使用 using 块,则 Thread.Join 方法将在未完成的情况下关闭。但是,如果我确实调用 Dispose 或使用 using 块,突然 Thread.Join 按预期工作。为什么?

TLDR;

当通过终结器调用 Dispose 时,Thread.Join 不会等待完成。当显式调用 dispose 时(通过手动调用它或使用 using 语句),Thread.Join 等待完成。

【问题讨论】:

  • 你班的线程是后台线程吗?如果它是前台线程,那么在这两种情况下,调用线程都应该等到子线程完成。如果它是后台线程,那么 Thread.Join() 会强制主线程等待子线程完成。否则它会在不等待子线程的情况下完成。
  • @PiotrWolkowski 这是一个后台线程。但是当我将其更改为前台线程时。它退出的速度更快:/
  • 如果您至少可以显示您的MyClass 的一些代码,那将很有帮助。尤其是创建和启动线程的方法以及使用Thread.Join的部分。
  • @PiotrWolkowski 已更新。

标签: c# multithreading join using


【解决方案1】:

您缺少两条信息:

  • Thread.Join 不会关闭线程。相反,它一直等到线程完成执行。
  • using 只是在 try/finally 块中调用 Dispose 方法的语法糖。

为简单起见,您的代码相当于:

MyClass class = null;

try
{
    class = new MyClass();
    class.Run();
}
finally
{
    if (class != null)
    {
        class.Dispose();
    }
}

由于您的Dispose 方法调用Thread.Join,而Thread.Join 又会等待线程完成执行,因此您的应用程序不会过早退出。

【讨论】:

  • 但是一旦在我的第一个示例中调用了 Thread.join。线程没有完成执行。是因为申请被关闭了吗?是应用程序强行关闭线程吗?我也知道 using 做了什么,但是一旦我使用它,线程就会完成执行。即使我没有使用 using 语句,而是在应用程序退出之前调用了 class.Dispose(),线程也会完成执行。然而,当终结器调用 dispose 时,线程突然关闭。
  • @CodingMadeEasy 在您发布的第一个代码中,Dispose 无处调用
  • @KoolKiz 我知道我没有。我只是想说明当显式调用 dispose 时(使用 using 或 Dispose 方法)。线程完成执行。但是,如果我不使用 using 块并且我没有明确调用 .Dispose()。应用程序在未完成线程的情况下强制退出。
  • @CodingMadeEasy 我试图解释的是Thread.Join 是让你的程序等待线程完成执行的语句。由于您在 Dispose 中调用了 Thread.Join,因此当您调用 Dispose 时,您的程序将等待线程完成。而using只是调用Dispose的一种精巧方式,和手动调用差不多
  • @CodingMadeEasy 原始问题中没有提到终结器,因此有点难以理解;)在应用程序关闭期间,终结器只有几秒钟的执行时间,以避免阻塞应用程序。 stackoverflow.com/a/9941751/869621
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多