Raul Arrabales

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

Code Snippet

[ServiceHandler(ServiceHandlerBehavior.Concurrent)]

public IEnumerator<ITask> QueryFrameHandler(webcam.QueryFrame query)

{

if (_state.Image == null)

{

query.ResponsePort.Post(new webcam.QueryFrameResponse());

yield break;

}

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 = new byte[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 = new MemoryStream())

{

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 = new byte[(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);

}

}

yield break;

}




Re: Microsoft Robotics - Simulation Simulated WebCam exception in QueryFrame

Raul Arrabales

After declaring the method QueryFrameHandler as Exclusive and moving the size assignment to the try-catch statement I haven't had the InvalidOperationException again.. So it seems to work ok with these changes..






Re: Microsoft Robotics - Simulation Simulated WebCam exception in QueryFrame

KyleJ - MSFT

You are correct that the handler should be marked exclusive. This is because it is locking the Image object instead of just reading state. I'll make this change and also put it in the try-catch block for our next release.

Thanks for the bug report.

-Kyle