Могу ли я ссылаться на таймер по его тегу в VB.net ?

#vb.net

#vb.net

Вопрос:

Для моего проекта у меня есть много таймеров, которые управляют замиранием медиаплеера, у каждого таймера есть имя Fade_ , а затем уникальный индексный номер, начинающийся с 0 , т. е. Fade_0 , Fade_1 Fade_2 и т. д.

Я хочу найти простой способ ссылаться на эти таймеры, чтобы я мог их запускать, однако я не могу найти простой способ сделать это.

Я пробовал следующее, но таймеры не классифицируются как элементы управления, и поэтому это не работает.

 Dim MyFadeTimer As Timer = Controls.Find("Fade_" amp; KeyIndex, True)(0)
MyFadeTimer.Enabled = True
  

Как я могу добиться подобного?

РЕДАКТИРОВАТЬ: используя глобальный список pf Dim FadeTimers As New List(Of Timer) , я могу ссылаться на них, но при заполнении списка с помощью Dim FadeTimers As New List(Of Timer)({Fade_0, Fade_1, Fade_2...}) я получаю сообщение об ошибке, в котором говорится, что в списке ничего нет, когда я вызываю его с помощью FadeTimers(KeyIndex).start() . Однако, когда я заполняю список, используя `FadeTimers.AddRange({Fade_0, Fade_1, …}) это работает?

Почему первый метод заполнения списка не работает, а второй работает?

Комментарии:

1. Как вы ссылаетесь на них в принципе, если они не являются элементами управления?

2. Вы не можете добиться аналогичной вещи, потому что нет подобной коллекции, в которую Timers добавляются. Если вам нужна коллекция, содержащая ваш Timers , вам нужно ее создать. Затем вы можете получить его по индексу, Tag или вы можете использовать Dictionary . Тем не менее, как вы думаете, сколько Timers вам нужно? В большинстве случаев, когда я видел, как люди используют несколько, им на самом деле нужен только один. Нет причин, по которым вы не можете Tick использовать его несколько раз через разные интервалы.

3. @jmcilhinney Мой проект представляет собой виртуальное пианино, и мне нужно использовать таймер, чтобы отключить звук после отпускания клавиши. Поскольку на моем пианино вы можете нажимать более одной клавиши одновременно, мне нужно иметь таймер для каждой клавиши.

4. @GSerg я в замешательстве, что вы имеете в виду?

5. Да, вы должны использовать AddRange() . Порядок имеет значение, инициализация списка выполняется слишком рано. Прежде чем конструктор смог завершить вызов метода InitializeComponent() . Таким образом, переменные по-прежнему ничего.

Ответ №1:

Вы могли бы добавить их все вручную в List(Of Timer) :

 Public Class Form1

    Private KeyIndex As Integer
    Private Timers As New List(Of Timer)({Fade_0, Fade_1, Fade_2, Fade_3, Fade_4})

    Private Sub Foo()
        Timers(KeyIndex).Start()
    End Sub

End Class
  

Вариантом может быть заполнение списка из события Load():

 Public Class Form1

    Private KeyIndex As Integer
    Private FadeTimers As New List(Of Timer)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        FadeTimers.AddRange({Fade_0, Fade_1, ...}) 
    End Sub

End Class
  

Если вы не хотите перечислять их все, вы можете использовать отражение, чтобы найти их. Обратите внимание, что мы должны добавить символ подчеркивания «_» перед именем таймера. Это делается только один раз, при загрузке формы:

 Public Class Form1

    Private KeyIndex As Integer
    Private Timers As New List(Of Timer)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim fi As Reflection.FieldInfo
        Dim flags As Reflection.BindingFlags = Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic
        For i As Integer = 0 To 4 ' <-- Change the 4 to the highest number of your Timers
            fi = Me.GetType.GetField("_Fade_" amp; i, flags)
            If Not IsNothing(fi) Then
                Timers.Add(fi.GetValue(Me))
            End If
        Next
    End Sub

End Class
  

Затем вы можете получить доступ к таймерам по индексу, как в первом примере:

 Timers(KeyIndex).Start()
  

Комментарии:

1. Привет, я попробовал первый предложенный вами метод, но теперь я получаю сообщение об ошибке при вызове . Start(): «System.NullReferenceException: «Ссылка на объект не установлена для экземпляра объекта». System. Коллекции. Generic.List<T>.this[int].get ничего не вернуло.» и я не знаю почему? Я сделал именно так, как вы сказали, и создал новый список таймеров.

2. Обновите свой пост выше своим новым кодом, и мы поможем вам разобраться.

3. Любопытно, что если я заполняю список, используя .AddRange then, он работает, но не с Private Timers As New List(Of Timer)({Fade_0, Fade_1, Fade_2, Fade_3, Fade_4})

4. Я не уверен, почему первый синтаксис не сработал для вас. Это отлично сработало для меня в моем тестировании. Я заполнил его, извлек таймер по значению индекса и активировал его.

5. Я понял это, чтобы не использовать .AddRange , мне просто нужно было не использовать список в качестве глобальной переменной, что, похоже, сработало для меня