问题描述
在一个用Windows窗体捕获相机的小项目上,我遇到了跨线程无效异常。我正在使用异步任务,但是在不禁用跨线程异常的情况下,无法找到从任务例程更新PictureBox元素的正确方法。避免这种情况的正确方法是什么?我尝试了Invoke所需的逻辑,但随后MainForm元素出现了相同的异常
private void InitCameraBtn_Click(object sender,EventArgs e)
{
if (InitCameraBtn.Text.Equals("Init Camera"))
{
StartCamera();
InitCameraBtn.Text = "Stop Camera";
isCameraRunning = true;
}
else
{
capture.Release();
InitCameraBtn.Text = "Init Camera";
isCameraRunning = false;
}
}
private async void StartCamera()
{
//cameraThread = new Thread(new ThreadStart(CameraThreadCallback));
//cameraThread.Start();
var r = await CameraThreadCallback();
}
public async Task<int> CameraThreadCallback()
{
return await Task<int>.Run(() =>
{
frame = new Mat();
capture = new VideoCapture(0);
capture.Open(0);
if (capture.IsOpened())
{
while (isCameraRunning)
{
capture.Read(frame);
image = BitmapConverter.ToBitmap(frame);
if (CameraBox.Image != null)
{
CameraBox.Image.dispose();
}
//CameraBox.Image = image;
setimage(image);
}
}
return 0;
});
}
private void setimage (Bitmap i)
{
//MainForm.CheckForIllegalCrossthreadCalls = false;
CameraBox.Image = i;
Thread.Sleep(500);
}
解决方法
您应使用以下方法更新“相机”框:
private void SetCameraBoxImage(Image image)
{
if (CameraBox.InvokeRequired)
{
var d = new SafeCallDelegate(SetCameraBoxImage);
CameraBox.Invoke(d,new object[] { image});
}
else
{
CameraBox.Image = image;
}
}
因此,不要使用CameraBox.Image = value
我认为您正在尝试从另一个线程访问Windows窗体控件。在这种情况下,您需要进行线程安全的调用
public async Task<int> CameraThreadCallback()
{
return await Task<int>.Run(() =>
{
frame = new Mat();
capture = new VideoCapture(0);
capture.Open(0);
if (capture.IsOpened())
{
while (isCameraRunning)
{
capture.Read(frame);
image = BitmapConverter.ToBitmap(frame);
CameraBox.Invoke(new Action(() =>
{
if (CameraBox.Image != null)
{
CameraBox.Image.Dispose();
}
CameraBox.Image = image;
})):
}
}
return 0;
});
}