2011-05-04 7 views
1

스레드를 사용하여 웹 사이트에서 이미지를 가져 와서 부모 폼 (WPF)으로 다시 표시하여 표시합니다. 나는이 문제에 실행하고이 예에 디버깅 관리해야 : 시계()가 자신의 스레드에서 실행되는WPF 이미지 스레딩 (System.InvalidOperationException)

public void Watch() 
{ 
    while (true) 
    { 
    Bitmap bmp = new Bitmap(1, 1); 
    BitmapImage bmpImg = new BitmapImage(); 

    this.SetImage(bmp, bmpImg); 
    } 
} 

public delegate void SetImageCallback(Bitmap bmp, BitmapImage bmpImg); 

private void SetImage(Bitmap bmp, BitmapImage bmpImg) 
{ 
    if (!this.imgVideo.Dispatcher.CheckAccess()) 
    { 
    SetImageCallback del = new SetImageCallback(SetImage); 
    this.Dispatcher.Invoke(del, bmp, bmpImg); 
    } 
    else 
    { 
    Bitmap bitmap = bmp; 
    BitmapImage bitmapImage = bmpImg; 
    } 
} 

염두에 두십시오. Window Form에서 PictureBox와 함께 사용할 수있는 비트 맵 객체를 사용하면 모든 것이 훌륭하게 작동합니다. 즉,이 코드를 디버깅 할 때 라인에 도달했을 때

변수를 검사하면 모든 것이 잘되고 예상대로 작동합니다. 나는 다음 줄

BitmapImage bitmapImage = bmpImg; 

에 그리고 변수 bmpImage inpsect 얻을 때, 나는 System.InvalidOperationException의 톤을 얻을. 이것이 실제로 실용적이고 WPF Image 객체에 할당되면 "다른 스레드가 소유하고 있기 때문에 호출하는 스레드는이 객체에 액세스 할 수 없습니다"라고 표시됩니다. WPF BitmapImages (ImageSource를 설정하는 데 필요하지만 Windows Forms Bitmap 객체 (PictureBox를 설정하는 데 사용할 수 있음)를 사용하여이 문제가 발생하는 이유는 무엇입니까? WPF에서 어떻게 수정합니까?

+0

읽기이 : http://msdn.microsoft.com/en-us/library/ms750509.aspx –

답변

4

WPF의 대부분의 개체는이 범주에 속합니다. 다른 스레드간에 개체를 공유 할 수 없습니다. 그러나 브러시 및 비트 맵과 같은 특정 저수준 자원은 Freezable이라는 특수 클래스에서 파생되므로 을 다른 스레드간에 공유 할 수 있습니다. 물론 일단 개체가 고정되면 더 이상 어떤 식 으로든 수정할 수 없습니다. freezable 객체를 고정하려면 Freeze을 호출하면 크로스 스레드 예외가 방지됩니다. 대신

+0

좋아, 그래서 나는 BitmapImage 및 (A BitmapImage에 할당 된 소스와 함께)를 ImageBrush와 모두 시도 시작했다 및 "이 Freezable을 고정 할 수 없습니다"오류가 계속 발생합니다. 나는 왜 이것을 얻고 있는가? – jack1818

+0

URL에서 이미지 원본을 가져 오는 것과 관련이 있습니까? 내가 [이] (http://social.msdn.microsoft.com/Forums/en/wpf/thread/ea848447-abcd-42af-9f2c-18817afd874f) 문제를 겪고 있지만 DownloadCompleted 이벤트를 발생시킬 수없는 것 같습니다. 또한 IsDownlading 속성을 확인하면 항상 true입니다. 어떻게해야합니까? – jack1818

+0

이 솔루션이 작동합니다! –

1

if (!this.imgVideo.Dispatcher.CheckAccess()) 
    { 
    SetImageCallback del = new SetImageCallback(SetImage); 
    this.Dispatcher.Invoke(del, bmp, bmpImg); 
    } 

사용해보십시오 :

여기
if (!App.Current.Dispatcher.CheckAccess()) 
       App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action<CustomObject>(SetImage),CustomeObjectInstance); 

Cutom 객체가

Bitmap bmp, BitmapImage bmpImg 

분명히 랩하는 래퍼 클래스 될 것입니다, 당신의 SetImage 서명이

로 변경됩니다
SetImage(CutomObject custObj) 

코드를 테스트하지 않았지만 문제가 해결 될 수 있습니다. 가난한 영혼이이 게시물에서 이익을 얻을 수 있도록 작동하는지 알려주세요. 최고! 시드

+1

좋은 생각이지만 작동하지 않습니다. 같은 예외. – jack1818