考虑以下代码:
public class ChainHandler
{
public void ProcessTopUp(string amount, string phone, ResponseCallback responseCallback)
{
var statebag = GetStateBag();
ICommand basecommand = new BlmLoginCommand(statebag);
basecommand .SetNext(new BlmDynamicCommand(statebag, RequestMessageEvent.TCD_RecargaTAE10, new Dictionary<string, string> { { "amt", amount }, { "cel", phone } }))
.SetNext(new BlmDynamicCommand(statebag, RequestMessageEvent.TCD_BuyProduct))
.SetNext(new BlmEndCommand(statebag, responseCallback));
basecommand.ExecuteAsync();
}
}
class Program
{
static void Main(string[] args)
{
ChainHandler ch = new ChainHandler();
ch.ProcessTopUp("5.00", "0123456789", OnProcessResponse);
Console.ReadLine();
}
private static void OnProcessResponse()
{
//...
}
}
方法“ExecuteAsync”启动使用命令的异步流程。 命令在内部异步使用 Socket 类(基于事件的异步模式)。
问题是:是否有可能永远不会到达 EndCommand,因为对象基命令在离开“ExecuteAsync”方法后被释放?
连.net都知道EndCommand有回调方法吗?
或者 .net 是否足够智能,可以让对象保持事件状态直到异步流程完成?
如果对象没有保持事件状态,我可以做什么来指示垃圾收集器不要处置基本命令?
最佳答案
准确性在这里很重要。对象不会自动处置。它始终在代码中通过 using 语句或调用 Dispose() 方法显式完成。因此,如果您不在代码中进行 dispose ,则永远不会出现问题。
您可能想说的是“垃圾收集”。这在 .NET 中非常简单,只要垃圾收集器可以看到对对象的引用,并且该引用由本身处于事件状态的另一个对象持有,那么该对象就不会被收集。
然而,该引用的存储位置并不总是那么清楚。 C# 编译器可以重写您的代码并将其从类中的方法移动到隐藏类的方法。该隐藏类有一个难以形容的名称,并且有一个存储引用的字段。垃圾收集器可以看到它,从而防止对象被收集。将代码中的引用复制到该隐藏类对象的字段中的技术术语是 "variable capturing" .
C# 中的很多地方都使用了这种代码重写技巧。最初以支持匿名方法和迭代器的语言实现。并在以后的版本中进行了扩展,实现了lambda表达式和异步方法。了解正在发生的情况的一个好方法是查看 C# 编译器生成的代码。使用 ildasm.exe 或不完美的反编译器可见。否则,这肯定符合“足够聪明”的绰号。
关于c# - 是什么阻止对象被处置?/异步流是否使对象保持事件状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16831611/