3

在我的 c# 程序中,我在主(UI)线程中创建了一堆按钮。然后我启动一个运行方法的计时器Timeline()Timeline()现在我希望在方法运行时更改按钮的外观。但是我不允许访问这些对象,因为它们归主线程所有。我该如何解决这个问题?

错误:The calling thread cannot access this object because a different thread owns it.

我发现Dispatcher disp = Dispatcher.CurrentDispatcher;which 有一个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;
            }
        }
4

4 回答 4

3

您需要使用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)));
于 2012-10-09T07:25:35.177 回答
1

你就是这样做的——

Button1.Invoke(new MethodInvoker(delegate {
// Executes the following code on the GUI thread.
Button1.BackColor="Red";}));
于 2012-10-09T07:06:38.410 回答
0

尝试用

Application.Current.Dispatcher.BeginInvoke((ThreadStart)delegate
{
    // TODO: Implement task to do on main thread
});

必须始终在主线程上访问控件。

于 2012-10-09T07:00:56.413 回答
0

是的,需要使用Invoke方法。它在 Dispatcher 关联的线程上同步执行指定的委托。

于 2012-10-09T07:02:14.400 回答