在“使用”块中处理线程时中止线程

时间:2018-11-27 13:25:12

标签: c# multithreading

我正在启动一个这样的线程:

nameOfThread = new Thread(() => 
{
    //do stuff
});
nameOfThread.Start();

在此匿名函数内的某个时刻,我打开了一个WinSCP会话,如下所示:

using (Session session = new Session())
{
     //do stuff
}

如果我仍然在nameOfThread.Abort()内进行操作时(如从其他地方using中止线程),则该会话是否在末尾进行处理?

2 个答案:

答案 0 :(得分:3)

很有可能会,但是you can't be sure

根据文档:

  

在线程上调用此方法[Abort]时,系统会在线程中抛出ThreadAbortException来中止它。

我们知道,异常仍然会让using语句按其应有的处置。 (给出一些例外)

另一方面,如果可以优雅地结束线程(例如,以CancellationTokenSource结尾),则对您的应用程序会更好。它将提供对线程的实际终止和异常处理的更多控制。

答案 1 :(得分:1)

我回答了您可以保证using语句将始终调用Dispose并且我立场正确,我错了

using语句中存在潜在的竞态条件,不能保证销毁,并且我整理了一个控制台应用程序来说明这一点(这并不困难也不琐碎)

当显示IL如何生成using时,我是正确的:

var session = new Session(); //If this causes an error or abort happens during initialization then we don't enter try
//If abort is called here then we never enter try
//In either case above we may have undisposed resources initialized at this point
try
{
    //do stuff
}
finally
{
    session.Dispose();
}   

但是;请注意以下注释,其中显示了在输入try之前中止可能发生的竞争状况。

这里是一个控制台应用程序,旨在证明这一点。第一个可以按预期工作,但是如果您在初始化//thread.Abort()时添加注释掉的代码R,那么您将看到它的初始化内容,但从不丢弃:/

using System;
using System.Threading;

namespace Question_Answer_Console_App
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Start Main");

            Thread thread = null;
            thread = new Thread(new ThreadStart(() =>
            {
                Console.WriteLine("Thread Started");
                using (var r = new R(thread))
                {
                    Console.WriteLine($"Using {nameof(R)}");
                }
            }));

            thread.Start();
            thread.Join();

            Console.WriteLine("End Main");
            Console.ReadKey();
        }
    }

    public class R : IDisposable
    {
        public R(Thread thread)
        {
            Console.WriteLine($"Init {nameof(R)}");
            //thread.Abort();
        }

        public void Dispose()
        {
            Console.WriteLine($"Disposed {nameof(R)}");
        }
    }
}

带有//thread.Abort()的输出已被注释掉:

Start Main
Thread Started
Init R
Using R
Disposed R
End Main

未注释掉带有thread.Abort()的输出:

Start Main
Thread Started
Init R
End Main