2011-05-11 23 views
2

我知道這裏有很多類型的問題。我想發佈,以便我可以分享我的具體問題,因爲我感到沮喪。調用線程無法訪問此對象,因爲不同的線程擁有它。如何編輯圖像?

即時通訊運行一個線程,從數據庫查詢路徑,並把它放在圖像元素。問題是,我在xaml中創建圖像,所以當我運行此線程時,它拋出無法訪問此對象錯誤,它不能訪問圖像元件。

那麼如何設置它,而不使用XAML?這裏是我的代碼片段:

public partial class Window1 : Window 
{ 


    Thread Frame1; 

    public Window1() 
    { 
     InitializeComponent(); 
     intializeDb(); 
     #region start frame 1 thread 
     Frame1 = new Thread(frame1); 
     Frame1.SetApartmentState(ApartmentState.STA); 
     Frame1.IsBackground = true; 
     Frame1.Start(); 
     #endregion 

    } 

public void frame1() 
    { 
     string k; 

     command.CommandText = "SELECT * FROM imageframe1"; 
     sqlConn.Open(); 
     Reader = command.ExecuteReader(); 

     while (Reader.Read()) 
     { 
      BitmapImage logo = new BitmapImage(); 
      logo.BeginInit(); 
      k = (string)(Reader.GetValue(1)); 
      logo.UriSource = new Uri(k); 
      logo.EndInit(); 
      image1.Source = logo; //THROWS THE ERROR HERE.IT CANT ACCESS image1 
      Thread.Sleep(1000); 
     } 
     sqlConn.Close(); 
     Reader.Close(); 

    } 

我怎麼會訪問image1呢?如果我在線程中創建一個新的,我將不得不作爲一個面板的孩子,然後我會得到一個錯誤,它不能訪問面板。

有什麼辦法解決這個問題嗎?很高興,如果有人可以根據我的代碼片段寫一個例子。

與仍然沒有成功,併產生了同樣的錯誤編輯:

public partial class Window1 : Window 
{ 
    public readonly SynchronizationContext mySynchronizationContext; 

public Window1() 
    { 
     InitializeComponent(); 

     mySynchronizationContext = SynchronizationContext.Current; 
     Frame1 = new Thread(frame1); 
     Frame1.SetApartmentState(ApartmentState.STA); 
     Frame1.IsBackground = true; 
     Frame1.Start(); 
    } 

public void frame1() 
    { 
     string k; 

     command.CommandText = "SELECT * FROM imageframe1"; 
     sqlConn.Open(); 
     Reader = command.ExecuteReader(); 



     while (Reader.Read()) 
     { 
      BitmapImage logo = new BitmapImage(); 
      logo.BeginInit(); 
      k = (string)(Reader.GetValue(1)); 
      logo.UriSource = new Uri(k); 
      logo.EndInit(); 
      SendOrPostCallback callback = _ => 
      { 
       image1.Source = logo; 
      }; 

      mySynchronizationContext.Send(callback, null); 

      //image1.Source = logo; 
      Thread.Sleep(1000); 
     } 
     sqlConn.Close(); 
     Reader.Close(); 

    } 
} 
+0

凍結()IT +調用 – 2011-05-11 10:58:33

回答

11

正如喬恩斯基特說,你可以用Dispatcher.Invoke到指定圖像,但是這還不夠,因爲BitmapImage已經在另一個線程創建的。爲了能夠使用它在UI線程上,你需要前Freeze它:

logo.Freeze(); 
Action action = delegate { image1.Source = logo; }; 
image1.Dispatcher.Invoke(action); 
+0

你真的救了我的命! thnx一堆!我從來沒有遇到過凍結.imitedim會去讀它理解什麼是再次發生.thnx。 – Psychocryo 2011-05-11 10:43:36

2

您使用與控制相關的Dispatcher要更新:

Action action = delegate { image1.Source = logo; }; 
image1.Dispatcher.Invoke(action); 

注意,使用Thread.Sleep這樣執行動畫不太可能提供非常好的體驗......尤其是當顯示線程必須獲取URI才能顯示圖像時。這不會很順利。

+0

就這樣?我應該在哪裏把它請help..yep,我知道嗎?它不會是smooth.thnx.but即時一個一個去here.later我想學習做適當的動畫。 – Psychocryo 2011-05-11 08:26:42

+0

現在我得到這個錯誤「異常已被調用的目標拋出。」 – Psychocryo 2011-05-11 08:28:00

+0

@Psychocryo:應將異常指定爲嵌套異常 - 查看完整的堆棧跟蹤,它應該解釋發生了什麼問題。 – 2011-05-11 08:34:37

0

我認爲這是因爲你沒有封送對UI線程的調用。你可以做這行:順便說一下

保存在構造方面,

// this is a class member variable 
public readonly SynchronizationContext mySynchronizationContext; 

// in ctor 
MySynchronizationContext = SynchronizationContext.Current; 

// in your method , to set the image:  
SendOrPostCallback callback = _=> 
{ 
    image1.Source = logo; 
}; 

mySynchronizationContext.Send(callback,null); 

,它的一個很好的做法是使用使用與SqlConnectionSqlDataReader語句。如:

using (SqlConnection conn = new SqlConnection("conn string here")) 
{ 
    using (SqlDataReader reader = cmd.ExecuteReader()) 
    { 
     // db access code 
    } 
} 
+0

我從Jon看到一個更優雅的解決方案。你是快的 – Menahem 2011-05-11 08:32:15

+0

我沒有得到它working.it返回與原始相同的錯誤。@ Menahem – Psychocryo 2011-05-11 08:37:00

+0

你在哪裏保存SynchronizationContext?它應該在'public Window1()'線程開始之前 – Menahem 2011-05-11 08:41:35

相關問題