我正在启动一个这样的线程:
nameOfThread = new Thread(() =>
{
//do stuff
});
nameOfThread.Start();
在此匿名函数内的某个时刻,我打开了一个WinSCP会话,如下所示:
using (Session session = new Session())
{
//do stuff
}
如果我仍然在nameOfThread.Abort()
内进行操作时(如从其他地方using
中止线程),则该会话是否在末尾进行处理?
答案 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