2012-06-07 2 views
0

저는 미디어 플레이어를 디자인하고 있으며 AddDirectory라는 메서드가 있습니다.이 메서드는 지정된 디렉터리의 모든 동영상을 미디어 플레이어의 데이터베이스에 추가합니다. 이 방법은 처리하는 데 시간이 걸리므로 사용자가 프로그램을 계속 사용할 수 있도록 백그라운드에서 실행하도록 결정했습니다. 나는 다음과 같은 이벤트 위임이 같은 클래스에서"다른 스레드가 소유하고 있기 때문에 호출하는 스레드가이 개체에 액세스 할 수 없습니다." C#

/// <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; 
    } 

: 여기

가 AddDirectory 방법 인 GUI가 알 수 있도록 내가이 이벤트를 필요

public delegate void MovieAddedHandler(MovieEventArgs e); 

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

을 때 새 영화 데이터베이스에 추가되었으므로 GUI를 업데이트하고 그에 따라 사용자에게 알릴 수 있습니다. 예를 들어 50 개의 영화가있는 디렉토리를 추가하면 50 번에 이벤트가 호출됩니다.

GUI 업데이트가 어려워졌습니다.

다음 코드 세그먼트는 사용자가 GUI에서 "디렉토리 추가"레이블을 클릭 할 때마다 호출되는 메소드의 일부입니다.

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

GetMovies() 메서드는 데이터베이스의 모든 동영상 목록 (별도 Movie 클래스로 표현됨)을 반환합니다. 그런 다음 GUI 격자의 모든 레이블을 지운 다음 다시 초기화하여 영화가 추가 될 때마다 사용자가 디렉토리의 나머지 영화를 기다리지 않고도 프로그램에서 즉시 영화에 액세스 할 수 있습니다. 추가 될 수 있습니다.

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

은 "라벨"변수는 데이터베이스에서 영화를 대표하는 모든 레이블의 목록입니다 :

오류 자체

는 방법)을 InitializeMovieLabels (호출됩니다. 표에 각 레이블을 추가하고 싶습니다.

오류는 (제목에 설명 된대로) : "다른 스레드가이 개체를 소유하고 있기 때문에 호출하는 스레드는이 개체에 액세스 할 수 없습니다."

저는 (매우) 미숙 한 일종의 스레드이며, 해결책을 찾으려고했지만 실패했습니다. 미안 내가 세부와 더불어 선외에 조금 갔다 :).

도움을 주시면 감사하겠습니다.

+5

이 페이지의 오른쪽에있는 "관련 항목"섹션을보십시오. – mbeckish

+0

"해결책을 찾고자했지만 실패했습니다." 제 질문을 생각해 보면, 당신이 독서에 괴롭다 고 생각합니다. 나는 모든 링크를 살펴 보았지만 적절한 해결책을 찾을 수 없었다. 오류는 같을 수 있지만 문제는 다릅니다. – Daniel

+1

Dispatcher를 사용하십시오. 자세한 내용이 필요하면 알려주세요. 답변을 추가하겠습니다. –

답변

0

다른 스레드에서 GUI를 업데이트하는 MethodInvoker을 사용하십시오.

labels.clear() 문은 다른 스레드에서 GUI를 업데이트하려고합니다. 따라서이 유형의 코드를 사용하십시오. 당신이 다른 스레드에서 GUI를 업데이트 할

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

MethodInvoker 대리자를 사용해야합니다.

+0

불평은 lables보다는 Grid에있었습니다. 완전히 스레드 안전성을 유지하려면 실제로 두 경우 모두 사용해야하지만 레이블은 백엔드 컬렉션으로 나타나고 호출의 영향을받지 않아야하며 그리드는 실제 그리드 개체와 비슷하게 생겼습니다. 'grid.Children.Add (..)'메소드 호출에이 같은 구조체를 사용하면된다. – Nevyn

관련 문제