Jeśli chcesz użyć timera, który ma własny wątek to nie można. UI może być zmieniane tylko z jego własnego wątku.
TextChangedEventArgs jest klasą z danymi zdarzenia. Taki pojemnik na dane, które chcesz przekazać w zdarzeniu. Jak definiujesz jakieś zdarzenie to tam powinny być dane specyficzne dla tego zdarzenia.
Dla Click Buttona masz
private void btnStart_Click(object sender, EventArgs e).
To EventArgs to jest odpowiednik TextChangedEventArgs mojego zdarzenia. U mnie tam jest tylko tekst ale możesz dodać np. DateTime czas {get;set} i będziesz miał w zdarzeniu czas zdarzenia.
Czyli
public class TextChangedEventArgs
{
public string Text { get; set; }
public DateTime czas { get; set; }
}
Oczywiście Text i czas trzeba ustawić jak wywołujesz zdarzenia
this?.OnTextChanged?.Invoke(this, new TextChangedEventArgs { Text = $"text changed {counter}", czas = DateTime.Now });
Ta linia wywołuje zdarzenia. Jeśli jakaś inna klasa będzie miała przypisaną metodę do obsługi tego zdarzenia. Dodatowo Tu Invoke po ?. powoduje, że jeśli nikt nie będzie nasłuchiwał tego zdarzenia to nie wywali błędu Object reference...
Nonameclass t = new Nonameclass();
t.OnTextChanged += T_OnTextChanged; // << subskrybuje zdarzenie OnTextChanged metodą T_OnTextChanged
Czyli w Nonameclass to
this?.OnTextChanged?.Invoke(this, new TextChangedEventArgs { Text = $"text changed {counter}", czas = DateTime.Now });
Wywołuje nam w Form to
private void T_OnTextChanged(object sender, TextChangedEventArgs e)
{
this.Invoke((MethodInvoker)delegate() { label1.Text = e.Text; });
}
bo mamy subskrypcję na zdarzenie: t.OnTextChanged += T_OnTextChanged;
I tu trzeba użyć Invoke dla kontrolki (może to być dla Form - this - jak u mnie lub dla jakiejś konkretnej kontrolki np. Label) bo to zdarzenie przychodzi z innego wątku niż wątek UI.
To powoduje niejako synchronizację wątku UI z wątkiem wywołującym zdarzenie. Pewnie fachowo to się jakoś inaczej nazywa.
I po co to się robi? Ano po to, żeby NonameClass nie musiała mieć wprost zależności do Form. Nanameclass nie powinna nic wiedzieć o Form i nie definiować referencji do Form. Nonameclass coś tam sobie robi i jak chce kogoś innego o czymś poinformować (np. że timer tiknął to uruchamia zdarzenie. Jeśli ktoś będzie nasłuchiwał tego zdarzenia, a może to być kilka różnych innych obiektów, to sobie to zdarzenie obsłużą po swojemu. UI pokaże cos w Labelu a inny obiekt może zapisać do pliku.
Zobacz, ze w Designerze formy dla Buttona masz np .cos takiego
this.button1.Click += new System.EventHandler(this.button1_Click);
ten System.EventHandler to też jest delegat.
public delegate void EventHandler(object sender, EventArgs e);
A Button przez dziedziczenie po Control ma zdefiniowane zdarzenie
public event EventHandler OnClick;
Czyli jest sobie delegat (w namespace System)
public delegate void EventHandler(object sender, EventArgs e);
i Button ma po Control dziedziczony event
public event EventHandler OnClick;
delegat jest określany jako wskaźnik na funkcję więc Designer przypisuje obsługę
this.button1.Click += new System.EventHandler(this.button1_Click);