在我的c#程序中,我在主(UI)线程中创建了一堆按钮。然后我启动一个运行方法Timeline()
的计时器。现在我希望在Timeline()
方法运行时更改按钮的外观。但我不允许访问对象,因为它们归主线程所有。我该如何解决这个问题?
错误:The calling thread cannot access this object because a different thread owns it.
我发现Dispatcher disp = Dispatcher.CurrentDispatcher;
有一个Invoke()
方法,但我不确定这是不是正确的方法,我无法让它工作。
以下是我的代码的一部分:
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;
}
}
答案 0 :(得分:2)
您需要使用Invoke/BeginInvoke
将更新转发到GUI线程:
int i1 = i; // local copies to avoid closure bugs
int j1 = j;
buttons[i1, j1].Dispatcher.BeginInvoke(
((Action)(() => buttons[i1, j1].Background = Brushes.Red)));
答案 1 :(得分:1)
你就是这样做的 -
Button1.Invoke(new MethodInvoker(delegate {
// Executes the following code on the GUI thread.
Button1.BackColor="Red";}));
答案 2 :(得分:0)
尝试使用
包装对按钮或整个(环绕它)的访问Application.Current.Dispatcher.BeginInvoke((ThreadStart)delegate
{
// TODO: Implement task to do on main thread
});
必须始终在主线程上访问控件。
答案 3 :(得分:0)
是的,需要使用Invoke
方法。它在与Dispatcher关联的线程上同步执行指定的委托。