Click to See Complete Forum and Search --> : System.Timers.Timer generating exception


foamy
December 13th, 2007, 03:31 AM
Hi guys,

I need some help on this one... I want this app to refill a datagridview every half minute, but as soon as my Timer's EventHandler executes FillCustomerList() I get an Exception:

InvalidOperationException:
The object '' was opened from another thread than the one it was created in.

How do I get around this?



public partial class Main : Form
{
private ArrayList Customers = new ArrayList();
private ArrayList UnitList = new ArrayList();
private ArrayList UnitTypes = new ArrayList();
private ArrayList TaskList = new ArrayList();

private DataGridViewCellStyle standard;
private DataGridViewCellStyle green;
private DataGridViewCellStyle yellow;
private DataGridViewCellStyle red;

Driver driver = Driver.Instance;

System.Timers.Timer myTimer;

public Main()
{
InitializeComponent();

standard = new DataGridViewCellStyle();
standard.BackColor = Color.LightSteelBlue;
standard.SelectionBackColor = Color.LightSteelBlue;

green = new DataGridViewCellStyle();
green.BackColor = Color.LightGreen;
green.SelectionBackColor = Color.LightGreen;

yellow = new DataGridViewCellStyle();
yellow.BackColor = Color.Yellow;
yellow.SelectionBackColor = Color.Yellow;

red = new DataGridViewCellStyle();
red.BackColor = Color.Red;
red.SelectionBackColor = Color.Red;

gridUnits.AutoGenerateColumns = false;
gridTasks.AutoGenerateColumns = false;
gridCustomers.AutoGenerateColumns = false;

gridUnits.DefaultCellStyle = standard;
gridTasks.DefaultCellStyle = standard;
gridCustomers.DefaultCellStyle = standard;
}

private void Main_Load(object sender, EventArgs e)
{
try
{
gridCustomers.Size = new Size(this.Size.Width - 20, this.Size.Height - 100);
chkCustomer.Location = new Point(5, gridCustomers.Size.Height - chkCustomer.Size.Height + 30);
FillCustomerList();
SetRowSize();
SetFontSize();

myTimer = new System.Timers.Timer();
myTimer.Interval = 30000;
myTimer.Elapsed += new ElapsedEventHandler(OnTick);
myTimer.Start();
}
catch
{

}
}

private void OnTick(object sender, System.Timers.ElapsedEventArgs e)
{
FillCustomerList();
SetRowSize();
SetFontSize();
}

private void FillCustomerList()
{
try
{
Customers.Clear();
gridCustomers.DataSource = null;
gridCustomers.Rows.Clear();

Customers = driver.GetAllCustomers();

gridCustomers.DataSource = Customers;

for (int i = 0; i < gridCustomers.Rows.Count; i++)
//TODO: Correct color according to status.
gridCustomers.Rows[i].Cells[1].Style = green;
}
catch
{

}
}

private void SetFontSize()
{
//Set Fonts to fill the screen.
int i = gridCustomers.Size.Height / gridCustomers.Rows.Count;

Font font = new Font("Calibri", i/3);
gridCustomers.Font = font;
}

private void SetRowSize()
{
//Set rows to fill the screen.
int rowcount = gridCustomers.Rows.Count;
int height = gridCustomers.Size.Height;
int average = height / rowcount;
for (int i = 0; i < rowcount; i++)
{
gridCustomers.Rows[i].Height = average;
}
}

Thread1
December 13th, 2007, 03:55 AM
try to use Invoke/InvokeRequired or use the timer control.

foamy
December 13th, 2007, 04:14 AM
try to use Invoke/InvokeRequired or use the timer control.
to do what ..?

Thread1
December 13th, 2007, 04:39 AM
oh here is another one using the SynchronizingObject property of the timer.. i've just edited your code, changes are in bold texts..


public partial class Main : Form
{
private ArrayList Customers = new ArrayList();
private ArrayList UnitList = new ArrayList();
private ArrayList UnitTypes = new ArrayList();
private ArrayList TaskList = new ArrayList();

private DataGridViewCellStyle standard;
private DataGridViewCellStyle green;
private DataGridViewCellStyle yellow;
private DataGridViewCellStyle red;

Driver driver = Driver.Instance;

System.Timers.Timer myTimer;

public Main()
{
InitializeComponent();

standard = new DataGridViewCellStyle();
standard.BackColor = Color.LightSteelBlue;
standard.SelectionBackColor = Color.LightSteelBlue;

green = new DataGridViewCellStyle();
green.BackColor = Color.LightGreen;
green.SelectionBackColor = Color.LightGreen;

yellow = new DataGridViewCellStyle();
yellow.BackColor = Color.Yellow;
yellow.SelectionBackColor = Color.Yellow;

red = new DataGridViewCellStyle();
red.BackColor = Color.Red;
red.SelectionBackColor = Color.Red;

gridUnits.AutoGenerateColumns = false;
gridTasks.AutoGenerateColumns = false;
gridCustomers.AutoGenerateColumns = false;

gridUnits.DefaultCellStyle = standard;
gridTasks.DefaultCellStyle = standard;
gridCustomers.DefaultCellStyle = standard;
}

private void Main_Load(object sender, EventArgs e)
{
try
{
gridCustomers.Size = new Size(this.Size.Width - 20, this.Size.Height - 100);
chkCustomer.Location = new Point(5, gridCustomers.Size.Height - chkCustomer.Size.Height + 30);
FillCustomerList();
SetRowSize();
SetFontSize();

myTimer = new System.Timers.Timer();
myTimer.Interval = 30000;
myTimer.Elapsed += new ElapsedEventHandler(OnTick);
myTimer.SynchronizingObject = this;
myTimer.Start();
}
catch
{

}
}

private void OnTick(object sender, System.Timers.ElapsedEventArgs e)
{
System.Timers.Timer t = (System.Timers.Timer)(sender);

t.Stop();
FillCustomerList();
SetRowSize();
SetFontSize();
t.Start();
}

private void FillCustomerList()
{
try
{
Customers.Clear();
gridCustomers.DataSource = null;
gridCustomers.Rows.Clear();

Customers = driver.GetAllCustomers();

gridCustomers.DataSource = Customers;

for (int i = 0; i < gridCustomers.Rows.Count; i++)
//TODO: Correct color according to status.
gridCustomers.Rows[i].Cells[1].Style = green;
}
catch
{

}
}

private void SetFontSize()
{
//Set Fonts to fill the screen.
int i = gridCustomers.Size.Height / gridCustomers.Rows.Count;

Font font = new Font("Calibri", i/3);
gridCustomers.Font = font;
}

private void SetRowSize()
{
//Set rows to fill the screen.
int rowcount = gridCustomers.Rows.Count;
int height = gridCustomers.Size.Height;
int average = height / rowcount;
for (int i = 0; i < rowcount; i++)
{
gridCustomers.Rows[i].Height = average;
}
}

foamy
December 13th, 2007, 04:56 AM
Thanks! :) it works perfectly now...