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?

Code Snippet

[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;

}

[4859 byte] By [RaulArrabales] at [2008-1-9]
# 1

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..

RaulArrabales at 2007-10-3 > top of Msdn Tech,Microsoft Robotics Studio,Microsoft Robotics - Simulation...
# 2

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

KyleJ-MSFT at 2007-10-3 > top of Msdn Tech,Microsoft Robotics Studio,Microsoft Robotics - Simulation...

Microsoft Robotics Studio

Site Classified