Периодически выполняемое задание на уровне библиотеки
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 04.05.20 07:43
Оценка:
Дано: Library, FW3.5-4.8/STD 2.0 и нулевой опыт многопоточного программирования под .NET

Решил добавить в неё кэш с ранее созданными объектами.

Если быть точнее, то это словарь [connectionString]->[объект connectionOptions].

И хочется прикрутить к этому словарю фоновую зачистку устаревших элементов.

Схема проста.

Поток пользователя
Блокирует словарь
{
 Запускает сборщик мусора (или не даем ему завершиться)
 Добавляет в словарь
}


Сборщик мусора
for(;;)
{
 Блокирует словарь
 {
  Удаляет устаревшие элементы

  Если словарь стал пустым, то завершаем работу
 }
 
 Sleep(1 сек)
}


Вопрос насчет выбора механизма для сборщика мусора.

Основные опасения — как этот фоновый сборщик мусора будет себя вести при завершении работы?

--- 1.
Сразу подумал про Thread+Sleep. Но решил пока не с ним связываться. Наверное это слишком дубовый способ.

--- 2.
Замутил тестовое приложение с использованием Timer.

Основная проблема — метод сборщика мусора может вызваться до завершения предыдущего вызова. Не очень красиво.

  Если интересно, то вот тестовый код
using System;
using System.Threading;

namespace ConsoleApp1{
////////////////////////////////////////////////////////////////////////////////
//class Program

class Program
{
 static object sm_LogGuard=new object(); 

 static object sm_Resource__Guard=new object(); 

 static int sm_Resource__Counter=0;

 static System.Threading.Timer sm_Resource__GC_Timer=null;

 //-------------------------------------------------
 static void Main(string[] args)
 {
  const string c_src="main";

  const int c_counter_init=9;

  for(int n0=0;n0!=10;++n0)
  {
   for(int n=0;n!=4;++n)
   {
    Helper__Log(c_src,"------------------ n: {0}",n);

    lock(sm_Resource__Guard)
    {
     if(sm_Resource__GC_Timer==null)
     {
      Helper__Log(c_src,"setup timer");
   
      sm_Resource__GC_Timer=new Timer(Resource_GC,null,0,1*1000);
     }
   
     if(sm_Resource__Counter==0)
     {
      Helper__Log(c_src,"set to {0}",c_counter_init);
   
      Interlocked.Exchange(ref sm_Resource__Counter,c_counter_init);
     }
     else
     {
      int x=Interlocked.Increment(ref sm_Resource__Counter);
   
      Helper__Log(c_src,"increment to {0}",x);
     }//else
    }//lock
   
    Thread.Sleep(2*1000);
   }//for n

   Helper__Log(c_src,"RESET");

   var t=Interlocked.Exchange(ref sm_Resource__GC_Timer,null);
    
   if(t!=null)
    t.Dispose();
  }//for[ever]

  Helper__Log(c_src,"EXIT");
 }//main

 //----------------------------------------------------------------------
 static void Resource_GC(object a)
 {
  string c_src=string.Format("GC_{0}",Thread.CurrentThread.ManagedThreadId);

  for(uint n=0;;)
  {
   ++n;

   lock(sm_Resource__Guard)
   {
    if(sm_Resource__Counter==0)
    {
     var t=Interlocked.Exchange(ref sm_Resource__GC_Timer,null);
    
     if(t==null)
     {
      Helper__Log(c_src,"Stop [ACHTUNG]!");
     }
     else
     {
      Helper__Log(c_src,"Stop GC");
    
      t.Dispose();
     }//if
    
     return;
    }
    
    if(n>3)
    {
     Helper__Log(c_src,"Exit");
     return;
    }
    
    var c=Interlocked.Decrement(ref sm_Resource__Counter);
    
    Helper__Log(c_src,"decrement to {0}",c);
   }//lock
  }//for[ever]
 }//Resource_GC

 //----------------------------------------------------------------------
 static void Helper__Log(string src,string format,params object[] p)
 {
  string msg=string.Format(format,p);

  lock(sm_LogGuard)
  {
   Console.WriteLine("[{0}][Thr {1}] {2}",DateTime.Now,src,msg);
  }
 }//Helper__Log
}//class Program

////////////////////////////////////////////////////////////////////////////////
}

--- 3.
"Слышал", что есть такая штука как Task....

-------------
Кто-нибуль может показать простой/надежный/правильный код для этой задачи?

Или не париться и заюзать Thread+Sleep?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.