1

WPFアプリで次のコードを実行しています。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        object obj = new object();
        Collection.Add(obj);
        Collection.CollectionChanged += new NotifyCollectionChangedEventHandler(delegate(object sender2, NotifyCollectionChangedEventArgs e2)
        {
            if (Collection.Count == 0)
                App.Current.MainWindow.Close();
        });

        Task.Factory.StartNew(() =>
            {
                //Do long running process
                Collection.Remove(obj); //this errors out
            });
    }

    private ObservableCollection<object> Collection = new ObservableCollection<object>();
}

エラーが発生しますSystem.InvalidOperationException:別のスレッドがオブジェクトを所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。

非同期タスクをキューに入れているという印象を受けたTask.Factory.StartNewので、スレッドは同じである必要がありますね。

4

2 に答える 2

3

Task.Factory.StartNewは、デフォルトのTaskSchedulerでアクションを実行するため、ThreadPoolで実行されます。

ObservableCollectionはスレッドセーフではありません。これは、UIコントロール(App.Current.MainWindow.Close())で操作を実行するCollectionChangedハンドラーが、タスクのアクションでコレクションの変更が行われているため、UIスレッドで実行されないことを意味し、エラーが発生します。見ています。

ハンドラーでUIを操作するだけでよい場合は、ディスパッチャーを使用できます。

Collection.CollectionChanged += new NotifyCollectionChangedEventHandler(delegate(object sender2, NotifyCollectionChangedEventArgs e2)
        {
            if (Collection.Count == 0)
                this.Dispatcher.BeginInvoke((Action)(()=> App.Current.MainWindow.Close()));
        });

バインドする必要がある場合は、スレッドセーフな実装の使用を検討してください。これを参照してください

于 2012-11-29T18:58:26.930 に答える
1

アーサーの答えに追加するために、私の実際のアプリケーション(上記のサンプルコードではない)では、MvvmLightビューモデルからこれを行う必要がありました。ViewModelからディスパッチャにアクセスするには:

アプリ内に、以下を追加します。

static App()
{
    DispatcherHelper.Initialize();
}

そして、を呼び出す代わりにthis.Dispatcher、ViewModelにはDispatcherへの参照がないため、以下が機能します。

DispatcherHelper.UIDispatcher.BeginInvoke((Action)(() => App.Current.MainWindow.Close()));
于 2012-11-29T19:21:24.303 に答える