In my c# program I create a bunch of buttons in the main (UI) thread. Then I start a timer that runs a method Timeline(). Now I want the appearance of the buttons to change when the Timeline() method runs. But I'm not allowed to access the objects because they are owned by the main thread. How do I solve this?
Error: The calling thread cannot access this object because a different thread owns it.
I have found Dispatcher disp = Dispatcher.CurrentDispatcher; which has an Invoke() method but I'm not sure if that is the right way, and I couldn't get it to work.
Here is part of my code:
private static SurfaceButton[,] buttons = new SurfaceButton[dimensionBeats, dimensionsNotes];
public SurfaceWindow1()
{
try
{
InitializeComponent();
}
catch (Exception ex)
{
}
LoadAudioContent();
// Add handlers for Application activation events
AddActivationHandlers();
InitializeButtons();
try
{
t = new Timer(Timeline, null, 1, dimensionBeats*500);
}
catch (Exception e)
{
}
}
private void InitializeButtons()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 6; j++)
{
SurfaceButton btn = new SurfaceButton();
//btn.Content = files[j].Substring(0,1);
btn.Name = "a" +i + j;
btn.Width = 120;
btn.Height = 120;
btn.ContactEnter+=StartSound;
btn.ContactLeave+=StopSound;
btn.Opacity = 0.01;
btn.ClickMode = ClickMode.Release;
buttons[i,j] = btn;
// add the newly generated button to the correct column (left to right one panel per column)
switch (i)
{
case 0:
rowPanel0.Children.Add(btn);
break;
case 1:
rowPanel1.Children.Add(btn);
break;
case 2:
rowPanel2.Children.Add(btn);
break;
case 3:
rowPanel3.Children.Add(btn);
break;
case 4:
rowPanel4.Children.Add(btn);
break;
case 5:
rowPanel5.Children.Add(btn);
break;
case 6:
rowPanel6.Children.Add(btn);
break;
case 7:
rowPanel7.Children.Add(btn);
break;
}
}
}
}
private void Timeline(Object state)
{
for (int i = 0; i < pressed.GetLength(0); i++)
{
sendRequest(url, postMethod, tabelId, buttsToString(butts));
for (int j = 0; j < pressed.GetLength(1); j++)
{
if (pressed[i,j])
{
buttons[i, j].Background = Brushes.Red;
}
}
Thread.Sleep(500);
for (int j = 0; j < pressed.GetLength(1); j++)
{
buttons[i, j].Background = Brushes.White;
}
}
You need to use Invoke/BeginInvoke to forward updates to the GUI thread:
int i1 = i; // local copies to avoid closure bugs
int j1 = j;
buttons[i1, j1].Dispatcher.BeginInvoke(
((Action)(() => buttons[i1, j1].Background = Brushes.Red)));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With