我对C#非常陌生,请原谅我,如果我不解释这个。
我从我的电脑摄像头中检索图像,并在PictureBox中显示它们,我将它们编码为jpeg并将它们发送到共享字典。这是我的代码:
void CurrentCamera_OnImageCaptured(object sender, CameraEventArgs e)
{
this.pictureBoxMe.Image = e.Image;
if (myName != "" && Form1.PicSent)
{
SendPic sendP = new SendPic((Image)e.Image.Clone());
new System.Threading.Thread(new System.Threading.ThreadStart(sendP.send)).Start();
}
}
public class SendPic
{
Image im;
public SendPic (Image im)
{
this.im = im;
}
public void send(){
Form1.PicSent = false;
var memoryStream = new MemoryStream();
im.Save(memoryStream, ImageFormat.Jpeg);
var byteArray = memoryStream.ToArray();
Form1.sd["/" + myName + "/video"] = byteArray;
memoryStream.Close();
Form1.PicSent = true;
}
}
问题是我得到了“对象目前在其他地方使用”。行上的错误:SendPic sendP = new SendPic((Image)e.Image.Clone());
基于我发现的其他论坛帖子,我已经更改了它,以便将图像传递给线程,这样它就是克隆。但是我仍然得到同样的错误(虽然现在崩溃之前它会持续更长时间)。
我读过一些关于锁定的内容?在这种情况下我该如何实现呢?或者我还需要做些什么吗?
感谢。
答案 0 :(得分:3)
它的行为就好像OnImageCaptured方法在一个线程上运行一样。这对于相机接口来说并非不太可能。设置一个断点并使用调试器的Debug + Windows + Threads窗口来查看运行此代码的线程。
失败模式是UI线程正在访问图像以绘制图片框,同时此工作线程调用Clone()。 GDI +不允许两个线程同时访问同一个图像对象。它确实是片状的,没有告诉UI线程开始绘画的确切时刻。 PicSent是另一个等待发生的事故。
答案 1 :(得分:1)
引起我注意的一件事是SendPic
类异步访问你的字典(行:Form1.sd["/" + myName + "/video"] = byteArray;
)。
但是,字典和哈希表不保证对写操作是线程安全的。如果您使访问字典的代码是线程安全的,那么您应该是安全的。一个简单的lock
将是一种开始的方式。
有点像这样:
public class SendPic
{
private object lockobj = new object();
// .... whatever other code ...
public void send()
{
// .... whatever previous code ...
lock(lockobj)
{
// assuming that the sd dictionary already has the relevant key
// otherwise you'd need to do a Form1.sd.Add(key, byteArray)
Form1.sd["/" + myName + "/video"] = byteArray;
}
// .... whatever following code ...
}
}
线程安全
字典<(Of<(TKey,TValue>)>)可以支持 同时多个读者,同样长 因为集合没有被修改。 即便如此,通过一个列举 集合本质上不是一个 线程安全的程序。 在罕见的 枚举争辩的情况 与写访问,集合 必须在整个过程中锁定 枚举。 允许收集 由多个线程访问 读书和写作,你必须 实现自己的同步。