在块中中止线程是否会'using'释放使用的实例



我正在启动这样的线程:

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

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

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

如果我中止线程(从其他地方(,就像nameOfThread.Abort()一样,同时仍在using内部执行任务,那么会话是否在最后被处理?

很可能会,但您不能确定。

根据文件:

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

我们知道异常仍然会让using语句按照它们应该的方式进行处理。(有几个例外(

另一方面,如果你能优雅地结束线程,例如用CancellationTokenSource,这对你的应用程序来说会更好。它将对线程的实际终止和异常的处理提供更多的控制。

我回答了您可以保证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之前中止,可能发生的竞争条件。

这里有一个控制台应用程序就是为了证明这一点而编写的。第一个如预期那样工作,但如果在初始化R时添加注释掉的代码//thread.Abort(),则您将看到它init,但永远不会丢弃:/

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

最新更新