2011-05-11 70 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

相关问题