3

私の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;
            }
        }
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

Invokeはい、メソッドを使用する必要があります。ディスパッチャが関連付けられているスレッドで、指定されたデリゲートを同期的に実行します。

于 2012-10-09T07:02:14.400 に答える
0

ボタンまたはボタン全体(ボタンの周りをループ)へのアクセスを次のようにラップしてみてください

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

コントロールは常にメインスレッドでアクセスする必要があります。

于 2012-10-09T07:00:56.413 に答える