0

私はメディアプレーヤーを設計しています。AddDirectoryというメソッドがあります。このメソッドは、指定されたディレクトリ内のすべての映画をメディアプレーヤーのデータベースに追加します。この方法は処理に時間がかかるため、ユーザーがプログラムを使い続けることができるように、バックグラウンドで実行することにしました。

AddDirectoryメソッドは次のとおりです。

    /// <summary>
    /// Adds all the movies in the specified directory and all its subdirectories to the database.
    /// </summary>
    /// <param name="path">A string representing the directory path.</param>
    /// <returns>True if all the files were added successfully, false otherwise.</returns>
    /// <exception cref="System.ArgumentException">Thrown if the path does not lead to a directory.</exception>
    public static bool AddDirectory(string path)
    {
        if (!FileProcessing.IsDirectory(path))
        {
            return false;
        }

        List<string> filePaths = FileProcessing.GetDirectoryMovieFiles(path); //a list containing the paths of all the movie files in the directory

        //add the movie in a separate thread so as to not interrupt the flow of the program
        Thread thread = new Thread(() =>
        {
            foreach (string filePath in filePaths)
            {
                AddMovie(filePath);
            }
        });

        //make the thread STA and start it
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();

        return true;
    }

同じクラスで、次のイベントとデリゲートがあります。

    public delegate void MovieAddedHandler(MovieEventArgs e);

    /// <summary>
    /// Called on when a movie is inserted into the database.
    /// </summary>
    public static event MovieAddedHandler MovieAdded;

このイベントが必要なのは、GUIがデータベースに新しい映画が追加されたことを認識し、GUIを更新して、それに応じてユーザーに通知できるようにするためです。したがって、たとえば50本の映画を含むディレクトリを追加すると、イベントは50回呼び出されます。

今、GUIの更新は私が苦労しているところです。

次のコードセグメントがあります。これは、ユーザーがGUIの[ディレクトリの追加]ラベルをクリックするたびに呼び出されるメソッドの一部です。

MovieInsertion.MovieAdded += (e2) =>
{
    this.movies = MovieDataRetrieval.GetMovies();
    this.labels.Clear();
    this.InitializeMovieLabels();
};

GetMovies()メソッドは、データベース内のすべての映画のリストを返します(別のMovieクラスで表されます)。次に、GUIグリッドのすべてのラベルをクリアしてから、それらを再度初期化します。これにより、ユーザーは、ムービーが追加されるたびに、ディレクトリ内の残りのムービーを待つことなく、プログラムですぐにムービーにアクセスできます。追加されます。

エラー自体は、InitializeMovieLabels()メソッドで呼び出されます。

foreach (Label labelIterator in labels)
{
    this.grid.Children.Add(labelIterator);
}

「labels」変数は、データベース内の映画を表すすべてのラベルのリストです。各ラベルをグリッドに追加したいと思います。

私が得るエラーは(タイトルで説明されているように):「別のスレッドがオブジェクトを所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。」

私はスレッドに(非常に)不慣れで、解決策を探してみましたが、失敗しました。詳細を少し船外に出してしまったらごめんなさい:)。

どんな助けでもいただければ幸いです。

4

1 に答える 1

0

MethodInvoker別のスレッドからGUIを更新する場合に使用します。

あなたのlabels.clear()ステートメントは別のスレッドからGUIを更新しようとします。したがって、このタイプのコードを使用してください。

if(this.labels.InvokeReqiured)
{
    this.labels.Invoke( (MethodInvoker) ( ()=> this.labels.Clear() ) );
}
else
this.labels.Clear();

別のスレッドからGUIを更新する場合は、必ずMethodInvokerデリゲートを使用してください。

于 2012-06-07T15:13:14.637 に答える