В своем приложении использую много фоновых задач.
Нужен счетчик активных задач. Для того чтобы корректно закрывать приложение дождавшись нулевого значения. Использую вместо Task.Factory.StartNew( ... ); TasksHub.StartNewTask( ... );
public static class TasksHub
{
private static int tasksActive = 0;
public static event EventHandler TasksActiveIsUpdated;
public static int TasksActive
{
get
{
return tasksActive;
}
set
{
tasksActive = value;
OnTasksActiveIsUpdated(null);
}
}
public static void OnTasksActiveIsUpdated(EventArgs e)
{
EventHandler handler = TasksActiveIsUpdated;
if (handler != null)
{
Application.Current.Dispatcher.Invoke(() => { handler(null, e); });
//handler(null, e);
}
}
public static Task StartNewTask(Action action)
{
lock (new object()) TasksActive++;
return Task.Factory.StartNew(() => {
action();
lock (new object()) TasksActive--;
});
}
public static Task<T> StartNewTask<T>(Func<T> function)
{
lock (new object()) TasksActive++;
return Task.Factory.StartNew(() => {
var result = function();
lock (new object()) TasksActive--;
return result;
});
}
}
Проблема в следующем. Счетчик TasksActive долгий период времени может иметь значение 1. Это понятно какая-то задача подвисает. Но TasksActive принимает и отрицательные значения. Каким образом TasksActive становится отрицательным я не могу понять.
Осмелюсь предложить такой вариант
static class TasksHub
{
private static bool _closed = false;
private static CountdownEvent _countdownEvent = new CountdownEvent(1);
public static Task StartNewTask(Action action)
{
_countdownEvent.AddCount();
try {
return Task.Factory.StartNew(() => {
try {
action();
}
finally {
_countdownEvent.Signal();
}
});
}
catch {
// если StartNew бросит исключение надо обязательно уменьшить счетчик
_countdownEvent.Signal();
throw;
}
}
public static Task<T> StartNewTask<T>(Func<T> function)
{
_countdownEvent.AddCount();
try {
return Task.Factory.StartNew(() => {
try {
return function();
}
finally {
_countdownEvent.Signal();
}
});
}
catch {
// если StartNew бросит исключение надо обязательно уменьшить счетчик
_countdownEvent.Signal();
throw;
}
}
public static int TasksCount
{
get {
return _countdownEvent.CurrentCount - (!_closed ? 1 : 0);
}
}
public static void CloseAndWait()
{
CloseAndWait(-1);
}
public static bool CloseAndWait(int millisecondsTimeout)
{
if (!_closed) {
_countdownEvent.Signal();
_closed = true;
}
return _countdownEvent.Wait(millisecondsTimeout);
}
}
class Program
{
static void Main(string[] args)
{
TasksHub.StartNewTask(() => {
Thread.Sleep(5000);
});
TasksHub.StartNewTask(() => {
Thread.Sleep(1000);
});
var b1 = TasksHub.CloseAndWait(10);
TasksHub.CloseAndWait();
}
}
Спасибо за помощь. В итоге переделал в следующий вид.
public static class TasksHub
{
private static int tasksActive = 0;
public static event EventHandler TasksActiveIsUpdated;
public static int TasksActive
{
get
{
return tasksActive;
}
}
public static void OnTasksActiveIsUpdated(EventArgs e)
{
EventHandler handler = TasksActiveIsUpdated;
if (handler != null)
{
Application.Current.Dispatcher.Invoke(() => { handler(null, e); });
}
}
private static void TasksActiveIncrement()
{
Interlocked.Increment(ref tasksActive);
OnTasksActiveIsUpdated(null);
}
private static void TasksActiveDecrement()
{
Interlocked.Decrement(ref tasksActive);
OnTasksActiveIsUpdated(null);
}
public static int GetTasksActive()
{
return tasksActive;
}
public static Task StartNewTask(Action action)
{
int startTimestamp = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
TasksActiveIncrement();
return Task.Factory.StartNew(() => {
action();
TasksActiveDecrement();
});
}
public static Task<T> StartNewTask<T>(Func<T> function)
{
int startTimestamp = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
TasksActiveIncrement();
return Task.Factory.StartNew(() => {
var result = function();
TasksActiveDecrement();
return result;
});
}
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Я преобразую входящий поток wav в mp3 через Lame этой функцией: