VB.NET Использование собственного таймера в лямбда-выражении в собственном выражении «New» - это нормально? - PullRequest
4 голосов
/ 01 октября 2010

Это работает, и я не могу представить, как это может вызвать проблемы, но Visual Studio дает мне предупреждение, и это меня огорчает. Мне просто интересно, может ли что-то подобное сделать когда-нибудь с проблемами:

У меня есть собственный таймер, который действует как ожидание в течение некоторого количества миллисекунд, а затем выполняет функцию. Это выглядит так:

Public Class MyTimer
    Inherits Timers.Timer

    Public Event Done()

    Public Sub New(ByVal interval As Double, ByVal repeat As Boolean, ByVal Work As DoneEventHandler)
        Me.AutoReset = Not repeat
    End Sub

    Private Sub ElapsedToDoneConvert() Handles Me.Elapsed
        RaiseEvent Done()
    End Sub
End Class

Я использую это так:

Dim Timer as New MyTimer(1000, False, Sub()
                                        ..code..
                                      End Sub)

или

Dim Timer as New MyTimer(1000, True, Sub()
                                        ..code..
                                      End Sub)

Первый случай ждет одну секунду, а затем выполняет ..code .., второй случай выполняет ..code .. многократно каждую секунду.

Теперь вопрос: представьте, что у меня есть форма с текстовым полем TextBox1. Это безопасно?

Dim Timer As MyTimer
Timer = New MyTimer(1000, True, Sub()
                                   If TextBox1.Text <> String.Empty Then
                                      MsgBox("TextBox1 is no longer empty")
                                      Timer.Stop()
                                   End If
                                End Sub)

(Таким образом, каждую секунду Таймер проверяет, является ли TextBox1 пустым. Если это не так, он отображает окно сообщения и прекращает проверку.)

Я получаю предупреждение, что Timer используется до того, как ему присвоено значение, но он используется в операторе, который присваивает его значение. Интервал таймера должен быть больше нуля. Есть ли что-то в этом, что я не понимаю, что может вызвать проблемы?

Спасибо за помощь!

Ответы [ 2 ]

2 голосов
/ 01 октября 2010

Проблема в том, что вы используете Timer в лямбде, который вы передаете конструктору MyTimer.Когда он компилирует эту строку:

Timer = New MyTimer(1000, True, Sub()
                                   If TextBox1.Text <> String.Empty Then
                                      MsgBox("TextBox1 is no longer empty")
                                      Timer.Stop()
                                   End If
                                End Sub)

Экземпляр Timer, который вы передаете, может использоваться конструктором MyTimer (компилятор не знает).Если это так и конструктор запускается до того, как результат присваивается Timer, вы передаете неинициализированное значение и получаете предупреждение.

Вы можете исправить это довольно легко:

Dim Timer As MyTimer = Nothing
Timer = New MyTimer(1000, True, Sub()
                                   If TextBox1.Text <> String.Empty Then
                                      MsgBox("TextBox1 is no longer empty")
                                      Timer.Stop()
                                   End If
                                End Sub)

То есть, сначала явно задайте для него значение «ничего».Я думаю, что это сработает, но на самом деле даже это вызывает у меня тревогу.Я бы изменил API так, чтобы вместо того, чтобы требовать передачи экземпляра таймера для обратного вызова, вы просто изменили его так, чтобы ваш обратный вызов возвращал либо true, либо false, независимо от того, хочет он продолжить или нет.Таким образом, MyTimer сам может быть ответственным за остановку, когда таймер возвращает false.

1 голос
/ 01 октября 2010

Вы действительно должны указать это в операторе использования, чтобы таймер удалялся каждый раз.Ваш класс MyTimer также должен реализовывать IDisposable.

...