0
Good morning, you guys.
I’m developing a C# library using Visual Studio for software authentication/licensing. It’s something simple. It basically consists of a method that executes a continuous loop by checking an xml file containing the license expiration date, the date of the last update of the file and compares this information with the date and time of the pc.
Three situations can be identified in this method:
- Authenticated licence
- Unpaid leave
- Date/time of the backdated pc
Each such situation will trigger an event containing this authentication information that should be dealt with within the software that I will develop in the future, such as the common events of controls and other Windows libraries. (In the case of this library of mine, it is something like the timer control, which triggers the tick event every time period)
So far so good. The problem occurs when I will use this authentication library on another system to display the authentication information in the form controls for the user. Error occurs: 'Invalid thread operation: accessed control of a thread that is not the one in which it was created.'
I found some methods that can get around this error, but they are implemented within the programs and I wanted something that could be encapsulated within that mine of the authentication library.
This is how events are triggered:
public delegate void MyDelegate(object sender, AuthenticationEventArgs e);
public event MyDelegate Authenticated;
public EsLicense(string FilePath, string Key)
{
//Carregamento de outras propriedades
this.t = new Thread(new ThreadStart(OnAuthentication));
}
public void StartTimer(int interval)
{
_interval = interval;
_running = true;
Load();
if (!t.IsAlive)
{
Load();
t.IsBackground = true;
t.Start();
}
}
protected virtual void OnAuthentication()
{
while (_running)
{
// Cria um novo objeto do tipo AuthenticationEventArgs
AuthenticationEventArgs e = new AuthenticationEventArgs();
if (DateTime.Now <= this.LastUpdate) //Verifica o relógio
{
//EXECUTA QUANDO O RELÓGIO DO SISTEMA ESTIVER INCORRETO
if (TimeZone.CurrentTimeZone.IsDaylightSavingTime(DateTime.Now)) //Verifica horário de verão
{
//Código para tratar erro quando o horário de verão acabar
}
// Verifica se existem métodos inscritos no eventos
if (Authenticated != null)
{
// Define os argumentos do evento
e.Status = AuthenticationStatus.SystemClockError;
e.Remaining = this.Remaining;
e.Exception = new Exception("O relógio do computador está desconfigurado. Configure a hora certa para poder continuar.");
// Dispara o evento
Authenticated.Invoke(this, e);
//Authenticated(this, e);
}
}
else
{
//EXECUTA ENQUANTO O RELÓGIO DO SISTEMA ESTIVER CORRETO
this.Update(); //Atualiza o último acesso
if (DateTime.Now < this.ExpirationDate) //Verifica a data de expiração da autenticação
{
//LICENÇA VÁLIDA
//Define a quantidade de dias que faltam até o vencimento da licença
this.Remaining = this.ExpirationDate.Subtract(DateTime.Now);
// Verifica se existem métodos inscritos no eventos
if (Authenticated != null)
{
// Define os argumentos do evento
e.Status = AuthenticationStatus.Validated;
e.Remaining = this.Remaining;
e.Exception = null;
// Dispara o evento
Authenticated.Invoke(this, e);
//Authenticated(this, e);
}
}
else
{
/*
* LICENÇA EXPIRADA
*
*/
//Define a quantidade de dias que faltam até o vencimento da licença
this.Remaining = new TimeSpan(0);
// Verifica se existem métodos inscritos no eventos
if (Authenticated != null)
{
// Define os argumentos do evento
e.Status = AuthenticationStatus.Expired;
e.Remaining = new TimeSpan();
e.Exception = null;
// Dispara o evento
Authenticated.Invoke(this, e);
//Authenticated(this, e);
}
}
}
Thread.Sleep(_interval);
}
}
Example of method that will handle the event:
private void Form1_Load(object sender, EventArgs e)
{
Licença = new EsLicense(@"C:\licença.xml", key);
Licença.Authenticated += new EsLicense.MyDelegate(Licença_Authenticated);
Licença.StartTimer(1000);
}
private void Licença_Authenticated(object sender, AuthenticationEventArgs e)
{
switch (e.Status)
{
case AuthenticationStatus.Validated:
textBox1.Text = e.Remaining.ToString(); // Linha onde o erro é disparado
break;
case AuthenticationStatus.Expired:
textBox1.Text = "Licença expirada";
break;
case AuthenticationStatus.SystemClockError:
MessageBox.Show("Erro de autenticação.\n\nO relógio do computador foi desatualizado", "Autenticação", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
break;
default:
break;
}
}
I’m a beginner in C# and I hope I was clear enough.
you don’t need to declare a
event
and adelegate
, in essence they do basically the same thing, have technical differences, but in your example just aevent
to solve your problem. Remove thedelegate
and invoke directly fromevent
. Now about the thread, explain better pq uses this, is pq the program can monitor multiple applications, and each runs in a thread?– Ricardo Pontual
@Ricardo Punctual, thank you for the comment. I did what you said, I removed the
delegate
and declared the event aspublic event EventHandler<AuthenticationEventArgs> Authenticated
, but the thread problem continues. I need to use thread because of thewhile
in the methodOnAuthentication()
. This method updates and monitors the authentication xml file at each time interval. If I don’t use a different thread the application simply hangs. In the example above I put the class instanceEsLicense
at the eventclick
button, but actually it will be in the eventLoad
mainform of the application– Eric Jhon
only the Timer is not enough? it itself is already a thread, if you just want every X times it looks at the file that is enough :)
– Ricardo Pontual
Yes, that’s the way I used this library, but I would like to learn more about the operation of events triggered by multithreaded methods of other classes and the manipulation of these events using the controls. I think it would even be a more elegant way to work without using extra components and encapsulating as much code as possible for reuse.
– Eric Jhon
in this case study more about your code, debug.. will realize that your code code create a thread and a timer, which makes no sense, only one of the two would solve this, good luck
– Ricardo Pontual
Precisely. I can use only timer, but would like to use only thread.
– Eric Jhon