Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Drawing to PlotAreaImage problem

I am successfully writing greyscale bitmap data in a Scattergraph to the PlotAreaImage. Bitmap data is updated to the PlotAreaImage every second. All is going well until I put up a cursor and begin to drag it about the graph. I get the error that states:

An unhandled exception of type 'System.InvalidOperationException' occurred in system.drawing.dll

Additional information: The object is currently in use elsewhere.

I think the PlotAreaImage is being used to draw the cursor and there is a conflict when I try to write to the PlotAreaImage as it may be locked for cursor draw. Is this correct?

Is there a way to get around this?

-Measurement Studio 7.1
-C#
-Windows XP

Thanks,
Scott
0 Kudos
Message 1 of 8
(4,400 Views)
How are you drawing the image to the plot area. Could you please post a small test project that reproduces this behavior? Thanks.

- Elton
0 Kudos
Message 2 of 8
(4,398 Views)
Here is the method I call to draw a byte array (_BMData) of data to the bitmap. This is one line of data. The user can plot each line from TopToBottom or BottomToTop. The line is added to the bottom or top of the PlotAreaImage. This code works really well and is fairly fast, but this one problem. My project is rather large and complicated but if necessary I could gen up a smaller version if you want me to.

Scott
P.S. the for loop below isn't showing up well. the for loop goes from 0 to lines.

protected virtual void TransferDataToBitmap()
{
//Monitor.Enter(this);
Bitmap bm = (Bitmap)_NIGraph.PlotAreaImage;
Debug.WriteLine(string.Format("BitmapDisplayCtrl TransferDataToBitmap() {0} wd, {1} ht",bm.Width, bm.Height));
// Get bitmap. Use the LockBits method to lock the data in memory.

Rectangle rec = new Rectangle(0, 0, bm.Width, bm.Height);
BitmapData bmd=null;
try
{
bmd = bm.LockBits( rec, System.Drawing.Imaging.ImageLockMode.ReadWrite, bm.PixelFormat);
}
catch( Exception ex)
{
Console.WriteLine("Problem in TransferDataToBitmap()! {0}",ex.Message);
return;
}

int lines = _BMData.Count;
int from;
if( _DirectionOfDataFlow == DataFlowDirection.TopToBottom )
from = lines;
else
from = bm.Height-lines;

// Put the data in the bitmap
for( int i=0;

// Get a pointer to the bitmap data
int ip = bmd.Scan0.ToInt32() + (from*bmd.Stride);
// Get the Lofar data for the current line num
byte [] bData = (byte[])_BMData[i];
// Copy that data to the linenum of the bitmap
try
{
Marshal.Copy(bData, 0, (IntPtr)ip, bmd.Width);
}
catch(ArgumentOutOfRangeException ex)
{
Console.WriteLine("Problem in TransferDataToBitmap(): Marshal.Copy - Source Array Len: {0},Amount to Copy: {1} - Error: {2}", bData.Length, bmd.Width, ex.Message);
}

if( _DirectionOfDataFlow == DataFlowDirection.TopToBottom )
from--;
else
from++;
}

// Unlock it
bm.UnlockBits(bmd);
//Monitor.Exit(this);

}


Message Edited by scottyoo on 04-06-2005 07:16 PM

Message Edited by scottyoo on 04-06-2005 07:16 PM

Message Edited by scottyoo on 04-06-2005 07:22 PM

Message Edited by scottyoo on 04-06-2005 07:22 PM

0 Kudos
Message 3 of 8
(4,413 Views)
It's hard to say what the problem is without having a project to debug into, but I suspect that the problem is related to the fact that you're directly manipulating the bits of the bitmap that the graph is holding on to. One alternate solution is that you could add an event handler for the graph's BeforeDrawPlotArea event and draw the plot area before the plots, cursors, etc. are drawn. Another alternate approach would be to manipulate the bits of a bitmap that the graph is not holding onto and set the new image to the PlotAreaImage property.

Another question is how are you updating the graph every second? Are you using a timer? If so, which timer? System.Windows.Forms.Timer or System.Timers.Timer? My real question is if this update is happening on another thread from the UI thread. Also, what is the call stack for the exception?

- Elton

Message Edited by Elton Wells on 04-06-2005 10:26 PM

0 Kudos
Message 4 of 8
(4,386 Views)
Elton,

I am using another thread to wait for dataready. When ready it gets the data and raises an event to my main form which in turn updates the graph bitmap. So it is updated asynchronously. Interesting to note that it does not have this problem if I use a windows.forms timer.

Scott
0 Kudos
Message 5 of 8
(4,370 Views)
That is definitely part of the problem, if not the problem, because Windows Forms controls are not thread-safe. Notice that the class overviews of all .NET Framework and Measurement Studio Windows Forms controls have a thread safety section that states:

"Only the following members are safe for multithreaded operations: BeginInvoke, EndInvoke, Invoke, InvokeRequired, and CreateGraphics."

See the .NET Quickstart article "Making procedure calls across thread boundaries" for information on how to access controls across threads in a safe manner.

The problem does not happen when you use a Windows Forms Timer because the Tick event fires on the UI thread. If you use Invoke/BeginInvoke from your other thread as described in the article linked above, you should see the same behavior as using the timer.

- Elton
0 Kudos
Message 6 of 8
(4,363 Views)
Yes. I am raising my own delegate. I will try MethodInvoker with BeginInvoke on Monday (I'm off today Fri.) and pass on the results. Thanks again, Elton. That's almost forsure the problem.

Scott
0 Kudos
Message 7 of 8
(4,359 Views)
Yes. This works perfect. I can use cursors, etc. without any problems. Thank you. Here is a snippet of my code.

// DataReceiver ThreadProc
private void DataReceiver()
{
.
.
.
MethodInvoker mi = null;
try
{
mi = new MethodInvoker(SendDataToQue);
}
//Thrown when the thread is interupted by the main thread - exiting the loop
catch (Exception we)
{
MessageBox.Show("ERROR: DataReceiver Thread - {0}", we.Message);
}

.
.
.
// Data ready, invoke method

try
{
BeginInvoke(mi);
}
catch (ThreadInterruptedException e)
{
}
.
.
.
}

Message Edited by scottyoo on 04-11-2005 11:28 AM

Message Edited by scottyoo on 04-11-2005 12:44 PM

0 Kudos
Message 8 of 8
(4,345 Views)