我正在启动这样的线程:
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