Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在其他线程运行之前抑制对象终结_C#_.net - Fatal编程技术网

C# 在其他线程运行之前抑制对象终结

C# 在其他线程运行之前抑制对象终结,c#,.net,C#,.net,假设我在类中有一些代码,其中一个方法立即返回结果,但在此之前调用后台任务 class CalculationPolicy { private readonly IRequestContext _reqContext; public CalculationPolicy(IRequestContext reqContext) { _reqContext = reqContext; } public ProcessResult Process

假设我在类中有一些代码,其中一个方法立即返回结果,但在此之前调用后台任务

class CalculationPolicy 
{
    private readonly IRequestContext _reqContext;

    public CalculationPolicy(IRequestContext reqContext)
    {
       _reqContext = reqContext;
    }

    public ProcessResult Process(object model) 
    {
        var response = new ProcessResult();

        // some synchronous processing ... 
          ............................

        // notifications go into other thread
        Task.Run(() => NotifyCallback(model));

        return response;
    }

    private void NotifyCallback(object model)
    {
       // some notification logic
       // that uses a field [_reqContext]
       string email = _reqContext.GetEmailFromClaims();
    }
}

我想知道垃圾收集器是否知道,在另一个线程上完成NotifyCallback方法之前,我的类的实例不应该被终结,就像垃圾收集器保持我的对象的状态不被垃圾收集器触及一样保留对对象的引用,因为
NotifyCallback
是一个实例方法。因此,只要由
Task.Run
创建的任务执行此委托,您的对象就不是垃圾收集的候选对象。

当不再有指向该对象的引用时,将收集该对象。安排任务时:

Task.Run(() => NotifyCallback(model));
委托具有对对象的隐式引用,因此在任务运行之前不会收集该委托

但要挑剔一点,你的问题特别是:

我想知道垃圾收集器是否知道,在另一个线程上的NotifyCallback方法完成之前,我的类的实例不应该被终结

您的对象可以被收集在NoTyyCalbButs>代码>的中间,如果它不再引用<代码>此< /代码>。例如:

private void NotifyCallback(object model)
{
   // some notification logic
   // that uses a field [_reqContext]
   string email = _reqContext.GetEmailFromClaims();

   // Do some stuff with email but do not access any field
   // From this point, the object can be collected at any time
   Console.WriteLine(email);   

   Console.WriteLine("Done");
}
从技术上讲,您的对象可以在
string email=\u reqContext.GetEmailFromClaims()之后的任何时候被收集。这应该不是问题,因为您不再使用类中的任何字段。在极少数情况下会出现问题(通常在与本机代码进行互操作时),您可以使用
GC.KeepAlive
保存引用并人为延长对象的生存期:

private void NotifyCallback(object model)
{
   // some notification logic
   // that uses a field [_reqContext]
   string email = _reqContext.GetEmailFromClaims();

   // Do some stuff with email but do not access any field
   Console.WriteLine(email);   

   Console.WriteLine("Done");

   GC.KeepAlive(this); // The GC won't collect the object before this line
}

但是在大多数情况下,你应该是好的。

是的,虽然“可以在中间收集”是一个对C程序员来说是不可见的优化。但问题的措辞如此精确,我觉得有必要在回答中同样精确:)