1

要件に従って、新しい UI スレッドで WPF ウィンドウを開く必要があります。

次のコードを使用して、メイン UI スレッドから新しい UI スレッドでウィンドウを開きます。

Thread winthread = new Thread(new ThreadStart(() =>
{
    SynchronizationContext.SetSynchronizationContext(
        new DispatcherSynchronizationContext(
            Dispatcher.CurrentDispatcher));
    Window windowObj = new Window();
    Grid gridObj = new Grid();
    MyUserControl ctrl = new MyUserControl();
    gridObj.Children.Add(ctrl);
    windowObj.Content = gridObj;

    windowObj.Show();
    System.Windows.Threading.Dispatcher.Run();
}));

winthread.IsBackground = true;
winthread.SetApartmentState(ApartmentState.STA);
winthread.Start();

MyUserControl上記のコードが実行されると、ウィンドウはコンテンツとして表示されます。マウスのダブルクリックイベントでユーザーコントロールを反転させるようなアニメーションを行っています。

それをダブルクリックすると、アプリケーションは次の例外をスローし始めます。

別のスレッドがこのオブジェクトを所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。

オンラインでSystem.Windows.Threading.Dispatcher.Run()

誰でもこの問題の解決策を提案できますか?

4

2 に答える 2

1

上記のコードは問題ありません。問題が何であれ、それはMyUserControl内の何かです。これらのクラスには共有要素が存在するか、メインスレッドが所有するオブジェクトへの参照が存在する必要があります。MyUserControl引数として渡されるオブジェクトなど、メインスレッド上に作成されたものやメインスレッドによって所有されている ものがないことを確認する必要があります。

または、メインスレッドを使用して(または内部のコンポーネントと)対話しようとしている可能性がありますMyUserControlctrl外部スレッド(つまり、メインスレッドなど)からアクションを実行する場合はctrl、invokeへの参照を保持して使用する必要があります-次のようなものです:

public partial class MainWindow : Window
{
    UserControl1 ctrl;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Thread winthread = new Thread(new ThreadStart(() =>
        {
            SynchronizationContext.SetSynchronizationContext(
                new DispatcherSynchronizationContext(
                    Dispatcher.CurrentDispatcher));
            Window windowObj = new Window();
            Grid gridObj = new Grid();
            ctrl = new UserControl1();
            gridObj.Children.Add(ctrl);
            windowObj.Content = gridObj;

            windowObj.Show();
            System.Windows.Threading.Dispatcher.Run();
        }));

        winthread.IsBackground = true;
        winthread.SetApartmentState(ApartmentState.STA);
        winthread.Start();
    }

    private void button2_Click(object sender, RoutedEventArgs e)
    {
        ctrl.Dispatcher.Invoke(new Action(() => ctrl.AddStuff()));
    }
}

ここではUserControl1、リストボックスを使用して単純なウィンドウを作成しました。

public partial class UserControl1 : UserControl
{
    private int i;

    public UserControl1()
    {
        InitializeComponent();
    }

    public void AddStuff()
    {
        listBox1.Items.Add("This is line : " + i.ToString());
        i += 1;
    }
}

上記の場合、メインスレッドがinvokeを使用していることを確認する必要があります。具体的にはctrl、呼び出しを処理するためにディスパッチャを参照していることを確認してください。メインスレッドは、独自のディスパッチャー(クロススレッドエラーの原因)を使用するのではなく、のディスパッチャーへの呼び出しをマーシャルctrlします。

MyUserControl少なくとも、例外が発生している場所にコード行を表示できれば便利です。

于 2012-11-20T12:05:35.283 に答える
-1

呼び出しの問題のように聞こえます:

別のスレッドでグリッド/ウィンドウを変更しようとしているので、解決するのはかなり簡単です。

スレッドを変更して変更を呼び出す

http://social.msdn.microsoft.com/forums/en-US/wpf/thread/360540eb-d756-4434-86f9-a3449f05eb55

于 2012-11-20T11:39:11.880 に答える