Simulated WebCam exception in QueryFrame
Hi, I have two services which subscribe to webcam service (the simulated one in this case) and both query frames in a regular bases (every 100 ms.)
The problem is that after a few seconds (some times it takes longer) I get an InvalidOperationException at the red marked line (see below) in the QueryFrameHandler method in file SimulatedWebcam.cs:
The runtime is complaining because Object (_state.Image) is currently in use elsewhere.
Is this a bug in the SimulatedWebcam service? Or am I doing something wrong?
As many services can be simultaneously quering frames to this service, shouldn't the method QueryFrameHandler be declared as Exclusive?
Should the size assignment moved within the next try-catch?
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
publicIEnumerator<ITask> QueryFrameHandler(webcam.QueryFrame query){
if (_state.Image ==null){
query.ResponsePort.Post(
new webcam.QueryFrameResponse());yieldbreak;}
Size size =
new Size((int)query.Body.Size.X, (int)query.Body.Size.Y);if (query.Body.Format ==Guid.Empty){
// raw image requested;BitmapData raw =
null;// size not specified
if(size.Width == 0)size = _state.Image.Size;
try{
raw = _state.Image.LockBits(
new Rectangle(Point.Empty, size),ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
int byteSize = raw.Height * raw.Stride;webcam.QueryFrameResponse response =
new webcam.QueryFrameResponse();response.TimeStamp = _state.LastFrameUpdate;
response.Frame =
newbyte[byteSize];response.Size =
new Size(raw.Width, raw.Height);response.Format =
Guid.Empty;System.Runtime.InteropServices.
Marshal.Copy(raw.Scan0, response.Frame, 0, byteSize);query.ResponsePort.Post(response);
}
catch (Exception ex){
query.ResponsePort.Post(Fault.FromException(ex));
}
finally{
if (raw !=null){
_state.Image.UnlockBits(raw);
}
}
}
else{
ImageFormat format =
new ImageFormat(query.Body.Format);using (MemoryStream stream =newMemoryStream()){
if (size == _state.Image.Size ||size.Width == 0 ||
size.Height == 0 ||
size.Width >= _state.Image.Width ||
size.Height >= _state.Image.Height)
{
size = _state.Image.Size;
_state.Image.Save(stream, format);
}
else{
using (Bitmap temp =new Bitmap(_state.Image, size))
{
temp.Save(stream, format);
}
}
webcam.QueryFrameResponse response =
new webcam.QueryFrameResponse();response.TimeStamp = _state.LastFrameUpdate;
response.Frame =
newbyte[(int)stream.Length];response.Size = size;
response.Format = format.Guid;
stream.Position = 0;
stream.Read(response.Frame, 0, response.Frame.Length);
query.ResponsePort.Post(response);
}
}
yieldbreak;}

