2012-03-06 58 views
0

我在WPF中使用EmguCV,我發現這個例子TP捕獲圖像,我想在我的一些其他方法Method3()中使用bs1,但我得到錯誤,該對象屬於一些其他線程,任何人都有任何想法是什麼問題? BS1畢竟是一個全局變量後WPF線程錯誤

BitmapSource bs1; 

private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     capture = new Capture();  ///capture image 

     timer = new DispatcherTimer();  // timer object 
     timer.Interval = new TimeSpan(500); 
     timer.Tick += new EventHandler(timer_Tick); 
     timer.Start(); 

    } 
    void timer_Tick(object sender, EventArgs e) 
    { 
     using ( Image<Bgr, byte> Frame = capture.QueryFrame()) 
     { 
      if (Frame != null) 
      { 
       bs1 = ToBitmapSource(Frame); 
webcam.Source = ToBitmapSource(Frame); // ToBitmapSource convert image to bitmapsource webcam is a picture in mainwindow 
       Frame.Save("fg.jpeg"); //this work but use lot of processing 

      } 
     } 
    } 


public void Method3_click (...) 
{ 
    use_of_bs1(bs1); 
} 


    private void use_of_bs1() 
    { 

     data.Text = "waiting..."; 

     System.Threading.ThreadPool.QueueUserWorkItem(Startwork); 
    } 


    private void Startwork(object state) 
    { 

     try 
     { 
      _work = _worker.bs1_analysis(bs1);  // it is where bs1 giving thread errorbs1_analysis is library function 
     } 
     catch (Exception ex) 
     { 
      Dispatcher.BeginInvoke(new ShowworkInformationDelegate(ShowworkInformation)); 
      MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); 
      return; 
     } 
     Dispatcher.BeginInvoke(new ShowWorkInformationDelegate(ShowWorkInformation)); 

    } 

/// ToBitmapsource功能

public static BitmapSource ToBitmapSource(Emgu.CV.IImage image) 
    { 
     using (System.Drawing.Bitmap source = image.Bitmap) 
     { 
      IntPtr ptr = source.GetHbitmap(); 
      BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ptr, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); 
      DeleteObject(ptr); 
      return bs; 
     } 
    } 
+0

看看http://blog.somecreativity.com/2008/01/10/wpf-equivalent-of-invokerequired/ – Mohit 2012-03-06 12:06:29

+1

考慮到你使用的是DispatcherTimer,我猜你的Tick()是在調度程序線程正確地被解僱,所以你不需要特別調度。有可能指定什麼函數引發這個錯誤?您發佈的代碼或您擁有的** NOT **代碼(例如'Capture'類或'ToBitmapSource()'funcion)? – 2012-03-06 12:34:00

+0

實際上方法3是引發錯誤的方法 method3是一個按鈕,它具有也使用bs1的線程的功能 – murmansk 2012-03-07 05:40:26

回答

1

如果您創建了一個wpf資源並希望在不同的線程上使用它,您可以在傳遞它之前在對象上調用Freeze()。這將使它在另一個線程上使用是不可變的和合法的。

+0

謝謝它做了訣竅 – murmansk 2012-03-07 07:21:43

1

從你所描述的東西,BS1的是與Window.Dispatcher相關的,所以當你訪問它裏面Method3() ,引發了一個例外。要解決這個問題,你可以做這樣的事情

public void Method3() 
{ 
    Action<BitmapSource> useBs1 = (source) => use_of_bs1(source); 
    if(Thread.CurrentThread == this.Dispatcher.Thread) 
     { 

    useBs1(bs1); 
} 
else 
{ 
    this.Dispatcher.Invoke(DispatcherPriority.Normal,userBs1, bs1); 
} 


} 
1

在計時器事件(timer_Tick)你在不同的線程的一個地方BS1屬於

您需要在執行事件主線程。例如:

void timer_Tick(object sender, EventArgs e) 
{ 
    Dispatcher.Invoke(DispatcherPriority.Normal, 
      new Action(
       delegate { 
    using ( Image<Bgr, byte> Frame = capture.QueryFrame()) 
    { 
     if (Frame != null) 
     { 
      bs1 = ToBitmapSource(Frame); 
      webcam.Source = ToBitmapSource(Frame); // ToBitmapSource convert image to bitmapsource 
      Frame.Save("fg.jpeg"); //this work but use lot of processing 

     } 
    }})); 
} 
+0

實際上它是方法3引發錯誤 – murmansk 2012-03-07 05:42:47

2

在WPF中,UI元素只能由創建它們的相同線程(除了可凍結元素)訪問和使用。在你的代碼中,bs1是在主UI線程中創建的。計時器是不同的線程不能訪問該資源。 每當你想要做的就是主UI線程上創建的UI元素的東西,做到以下幾點:

Dispatcher.Invoke(DispatcherPriority.Normal, new Action(()=>DoSomeCodeWithUIElement())); 

使用Dispatcher.Invoke,如果你想如果你想異步調用的操作同步或Dispatcher.BeginInvoke運行。 其中DoSomeCodeWithUIElement是一種訪問並最終更新UI元素的方法。