- Código: Selecionar todos
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Collections.Concurrent;
namespace Testando_semáforos
{
public delegate void addString(int indice,String texto);
public enum Comandos
{
Assumir_thread
}
public struct MessageS
{
public Comandos comando;
public int parametro;
}
public partial class Form1 : Form
{
private ConcurrentQueue<MessageS> fila_mensagens = new ConcurrentQueue<MessageS>();
private Semaphore semaphoro = new Semaphore(1, 1);
public Form1()
{
InitializeComponent();
}
private void addStringAux(int indice, String texto)
{
switch (indice)
{
case 0: lv_thread_01.Items.Add(texto);
break;
case 1: lv_thread_02.Items.Add(texto);
break;
}
}
public void addStringIntoLists(int indice, String texto)
{
if (InvokeRequired)
{
addString dlg = new addString(addStringAux);
Invoke(dlg, new Object[] { indice, texto });
}
else
addStringAux(indice, texto);
}
private void monitor_thread()
{
try
{
bloco_execucao();
}
catch (ThreadAbortException)
{
addStringIntoLists(0, "Abortado");
addStringIntoLists(1, "Abortado");
}
catch (ThreadInterruptedException)
{
}
}
private void bloco_execucao()
{
int indice = 0;
MessageS msg;
for (; ; )
{
if (fila_mensagens.TryDequeue(out msg))
{
indice = msg.parametro;
}
semaphoro.WaitOne();
addStringIntoLists(indice, "Agora sou eu " + DateTime.Now.ToString());
semaphoro.Release();
Thread.Sleep(1000);
}
}
private Thread monitor;
private void Iniciar_Click(object sender, EventArgs e)
{
lv_thread_01.Items.Clear();
lv_thread_02.Items.Clear();
monitor = new Thread(new ThreadStart(monitor_thread));
monitor.Priority = ThreadPriority.Lowest;
monitor.Start();
}
private void button1_Click(object sender, EventArgs e)
{
MessageS msg;
msg.comando = Comandos.Assumir_thread;
msg.parametro = 0;
fila_mensagens.Enqueue(msg);
}
private void button2_Click(object sender, EventArgs e)
{
MessageS msg;
msg.comando = Comandos.Assumir_thread;
msg.parametro = 1;
fila_mensagens.Enqueue(msg);
}
private void Parar_Click(object sender, EventArgs e)
{
if (monitor != null)
monitor.Abort();
}
private Thread monitor_secundario;
private void Fecha_Click(object sender, EventArgs e)
{
monitor_secundario = new Thread(new ThreadStart(monitor_semaforo));
monitor_secundario.Start();
}
private void button4_Click(object sender, EventArgs e)
{
monitor_secundario.Abort();
}
private void monitor_semaforo()
{
try
{
semaphoro.WaitOne();
for (; ; )
{
addStringIntoLists(0, DateTime.Now.ToString() + " Eu estou no controle");
addStringIntoLists(1, DateTime.Now.ToString() + " Eu estou no controle");
Thread.Sleep(1000);
}
}
catch (ThreadAbortException)
{
}
finally
{
if(semaphoro!=null)
semaphoro.Release();
}
}
private void direto()
{
int indice = 0;
MessageS msg;
try
{
for (; ; )
{
semaphoro.WaitOne();
addStringIntoLists(indice, "-> Thread direta " + DateTime.Now.ToString());
indice++;
if (indice > 1)
indice = 0;
msg.comando = Comandos.Assumir_thread;
msg.parametro = indice;
fila_mensagens.Enqueue(msg);
semaphoro.Release();
Thread.Sleep(1000);
}
}
catch (ThreadAbortException)
{
}
finally
{
try
{
semaphoro.Release();
}
catch (Exception)
{
}
}
}
private Thread monitor_direto;
private void button3_Click(object sender, EventArgs e)
{
monitor_direto = new Thread(new ThreadStart(direto));
monitor_direto.Start();
}
private void button5_Click(object sender, EventArgs e)
{
if (monitor_direto != null)
monitor_direto.Abort();
}
}
}
Alguns conceitos empregados acima:
Sincronização de acesso a recursos compartilhados com semáforos.
Envio de mensagem entre threads.
Criação e destruição de threads.
Obs.:
Para aqueles que não estão habituados com conceitos de sistemas operacionais, o método Thread.delay(X) não deixa o sistema em busywait. Ao invés disso, ele deixa a thread fora do scheduler do sistema operacional por um tempo mínimo do parametro X. (Em sistemas de tempo real esse tempo é exatamente X).
[/list]