抱歉英语不好。在我的项目中,我有两个任务。一个用于将来自IP摄像机和火帧准备事件的数据解码到UI。和其他观看相机不离线。 如果摄像头处于脱机状态,则会将Error事件处理程序抛出到UI线程。 UI线程调用方法Stop Camera。但任务没有停止。我做错了什么?
按钮点击事件,它的工作完美。
void BtnCamera_Click(object sender, EventArgs e)
{
if (cameraStream.FrameDecoderActive)
{
cameraStream.StopCameraPreview();
}
else
{
Task.Factory.StartNew(() => { cameraStream.StartCameraPreview();});
}
}
停止相机方法:
public void StopCameraPreview()
{
//cancel token source
StopFrameDecoding.Cancel();
StopFrameChecker.Cancel();
}
这是我的第一个任务代码:
private void Run(Stream cameraStream)
{
try
{
FrameDecoderActive = true;
//inicializacija
Extensions Extensions = new Extensions();
BinaryReader streamReader = new BinaryReader(cameraStream);
byte[] imageBuffer = new byte[1024 * 1024];
byte[] curentBuffer = streamReader.ReadBytes(readSize);
//kadru skaitymas
while (FrameDecoderActive)
{
StopFrameDecoding.Token.ThrowIfCancellationRequested();
int imageStart = Extensions.Find(curentBuffer, jpegHeader);
if (imageStart != -1)
{
//randa jpg pradžia kameros streme
int size = curentBuffer.Length - imageStart;
//copy nuo jpg pradžio iki buferio galo į image buferį
Array.Copy(curentBuffer, imageStart, imageBuffer, 0, size);
//skaito kadrus kol gauna cancel tokeną
while (FrameDecoderActive)
{
curentBuffer = streamReader.ReadBytes(readSize);
int imageEnd = Extensions.Find(curentBuffer, boundaryBytes);
//jeigu neranda jpg pabaigos nuskaitytame buferyje
if (imageEnd != -1)
{
Array.Copy(curentBuffer, 0, imageBuffer, size, imageEnd);
size += imageEnd;
//naujas kadras
byte[] frame = new byte[size];
Array.Copy(imageBuffer, 0, frame, 0, size);
LastFrameTime = DateTime.Now;
if (!FrameCheckerActive)
{
StopFrameChecker = new CancellationTokenSource();
Task.Factory.StartNew(() => { FrameChecker(); }, StopFrameChecker.Token);
}
FrameReady.Invoke(this, new FrameReadyEventArgs { FrameBuffer = frame, Bitmap = BitmapFactory.DecodeByteArray(frame, 0, frame.Length) });
//kopijuojam buferio likuti i buferio pradzia
Array.Copy(curentBuffer, imageEnd, curentBuffer, 0, curentBuffer.Length - imageEnd);
//uzpildom likusia tuscia vieta
byte[] temp = streamReader.ReadBytes(imageEnd);
Array.Copy(temp, 0, curentBuffer, curentBuffer.Length - imageEnd, temp.Length);
break;
}
Array.Copy(curentBuffer, 0, imageBuffer, size, curentBuffer.Length);
size += curentBuffer.Length;
}
}
}
}
catch (OperationCanceledException)
{
Error.Invoke(this, new ErrorEventArgs { ErrorCode = 101, Message = "Camera decoder Canceled" });
}
catch (Exception ex)
{
Error.Invoke(this, new ErrorEventArgs { ErrorCode = 999, Message = ex.Message });
}
cameraStream.Close();
FrameDecoderActive = false;
Error.Invoke(this, new ErrorEventArgs { ErrorCode = 0, Message = "Camera Stoped" });
}
第二项任务:
private async void FrameChecker()
{
FrameCheckerActive = true;
await Task.Delay(1000);
try
{
while (FrameDecoderActive)
{
StopFrameChecker.Token.ThrowIfCancellationRequested();
DateTime curentTime = DateTime.Now;
var dif = curentTime - LastFrameTime;
if (dif.Seconds > 2)
{
throw new TimeoutException("Camera Frame timeout");
}
await Task.Delay(1000);
}
}
catch (TimeoutException)
{
Error.Invoke(this, new ErrorEventArgs { ErrorCode = 100, Message = "Camera Frame Timeout" });
}
catch (OperationCanceledException)
{
Error.Invoke(this, new ErrorEventArgs { ErrorCode = 101, Message = "Frame Checker Canceled"});
}
catch (Exception ex)
{
Error.Invoke(this, new ErrorEventArgs { ErrorCode = 999, Message = ex.Message});
}
FrameCheckerActive = false;
}
答案 0 :(得分:0)
你的嵌套循环正在阻碍你。在你的第一项任务中,基本上是:
while (FrameDecoderActive)
{
StopFrameDecoding.Token.ThrowIfCancellationRequested();
// some other stuff
while (FrameDecoderActive)
{
// more stuff
// never checks for cancellation!
}
}
问题是内部循环从不调用StopFrameDecoding.Token.ThrowIfCancellationRequested()
。因此,一旦代码进入内部循环,它就再也不会检查是否请求取消。
答案 1 :(得分:0)
while (FrameDecoderActive)
{
//checking if cacelation thrown
StopFrameDecoding.Token.ThrowIfCancellationRequested();
//Search image start on buffer readed from camera stream
while (FrameDecoderActive)
{
// read while found image end then break
}
}