调用线程无法访问此对象,因为不同的线程拥有它。如何编辑图像?
我知道这里有很多类型的问题。我想发布,以便我可以分享我的具体问题,因为我感到沮丧。调用线程无法访问此对象,因为不同的线程拥有它。如何编辑图像?
即时通讯运行一个线程,从数据库查询路径,并把它放在图像元素。问题是,我在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();
}
}
正如乔恩斯基特说,你可以用Dispatcher.Invoke
到指定图像,但是这还不够,因为BitmapImage
已经在另一个线程创建的。为了能够使用它在UI线程上,你需要前Freeze
它:
logo.Freeze();
Action action = delegate { image1.Source = logo; };
image1.Dispatcher.Invoke(action);
你真的救了我的命! thnx一堆!我从来没有遇到过冻结.imitedim会去读它理解什么是再次发生.thnx。 – Psychocryo 2011-05-11 10:43:36
您使用与控制相关的Dispatcher
要更新:
Action action = delegate { image1.Source = logo; };
image1.Dispatcher.Invoke(action);
注意,使用Thread.Sleep
这样执行动画不太可能提供非常好的体验......尤其是当显示线程必须获取URI才能显示图像时。这不会很顺利。
就这样?我应该在哪里把它请help..yep,我知道吗?它不会是smooth.thnx.but即时一个一个去here.later我想学习做适当的动画。 – Psychocryo 2011-05-11 08:26:42
现在我得到这个错误“异常已被调用的目标抛出。” – Psychocryo 2011-05-11 08:28:00
@Psychocryo:应将异常指定为嵌套异常 - 查看完整的堆栈跟踪,它应该解释发生了什么问题。 – 2011-05-11 08:34:37
我认为这是因为你没有封送对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);
,它的一个很好的做法是使用使用与SqlConnection
和SqlDataReader
语句。如:
using (SqlConnection conn = new SqlConnection("conn string here"))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
// db access code
}
}
我从Jon看到一个更优雅的解决方案。你是快的 – Menahem 2011-05-11 08:32:15
我没有得到它working.it返回与原始相同的错误。@ Menahem – Psychocryo 2011-05-11 08:37:00
你在哪里保存SynchronizationContext?它应该在'public Window1()'线程开始之前 – Menahem 2011-05-11 08:41:35
冻结()IT +调用 – 2011-05-11 10:58:33