В C#, где я должен сохранить ссылку своего таймера?

Вы можете упростить свой код с другой перегрузкой Expression.SwitchCase

Просто создайте массив с тестовыми значениями и преобразуйте его в ConstantExpression. Попробуйте этот пример:

var writeLine = typeof(Console).GetMethod("WriteLine", new[] {typeof(string)});

// body of first block
var action1 = Expression.Call(writeLine, Expression.Constant("1 or 2"));
// body of second block
var action2 = Expression.Call(writeLine, Expression.Constant("3, 4 or 5"));

var value = Expression.Parameter(typeof(int), "value");
var body = Expression.Switch(value,
    Expression.SwitchCase(
      action1,
      new[] {1, 2}.Select(i => Expression.Constant(i))),
    Expression.SwitchCase(
      action2, 
      new[] {3, 4, 5}.Select(i => Expression.Constant(i)))
);

var lambda = Expression.Lambda>(body, value);
var method = lambda.Compile();

method(1); // print "1 or 2"
method(4); // print "3, 4 or 5"

14
задан Hosam Aly 25 January 2009 в 07:57
поделиться

3 ответа

Если Ваш Таймер является объектом прикладного уровня, что нет ничего неправильно с созданием его частный статический член Вашего Основного класса. Это - то, что я сделал бы, так или иначе.

18
ответ дан 1 December 2019 в 07:52
поделиться

Я думаю, что нормально сохранять, частное статическое поле Вашего класса.

Я сохранил бы эту ссылку как статическое поле вместо того, чтобы играть со сборщиком "мусора".

4
ответ дан 1 December 2019 в 07:52
поделиться

Править: Мой исходный ответ является мусором. Действительно мусор. Я сохранил его здесь для объяснения, почему это - мусор, хотя - это находится в комментариях, но они были бы удалены с ответом.

GC.KeepAlive только удостоверяется, что ссылку рассматривают как корень до окончания вызова. В коде в нижней части этого ответа метод GC.KeepAlive сразу назвали бы, и затем таймер будет все еще иметь право на сборку "мусора". Поскольку недавно созданный поток является приоритетным потоком, приложение будет работать, пока это живо (тогда как таймер использует фоновый поток, который не предотвращает выход программы). Это означает, что Основной метод выходит, но приложение должно продолжать бежать.

Возможно простое решение состояло бы в том, чтобы работать myThreadStart в основном потоке, вместо того, чтобы создать новый и затем позволить основному потоку умереть. Другими словами, простое решение было бы:

using System.Threading;

class Program {
    static void Main() {
        Timer timer = new Timer(myTimerCallback, 
                                new MyStateObject(), 0, 5000);
        myThreadStart();
        GC.KeepAlive(timer);
    }
}

Я предполагаю, что реальный код более сложен, хотя - в этом случае использование частной статической переменной, как предложено в других ответах является, вероятно, способом пойти. Это действительно будет зависеть от использования все же. Я лично предпочитаю не создавать статическое поле только ради предотвращения чего-то собираемого, если существует альтернатива (как вышеупомянутое), но иногда это - фактически единственный способ сделать его.

Исходный (плохой) ответ:

Если Вы действительно хотите выделить его в Основном, то можно использовать GC.KeepAlive:

using System.Threading;

class Program {
    static void Main() {
        new Thread(myThreadStart).Start();
        Timer timer = new Timer(myTimerCallback, 
                                new MyStateObject(), 0, 5000);
        GC.KeepAlive(timer);
    }
}
12
ответ дан 1 December 2019 в 07:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: