# thread issues. asynchronous callbacks need to modify control

## Recommended Posts

these two methods are callbacks being executed from another thread. As soon as BeginRender returns, the calling thread starts writing to the returned buffer. When it is done writing, it calls EndRender. Thus, I can't schedule this work to be done in the main thread by Invoke(), as the calling code will write before the image bits are locked. Its crashing sporadically in target_image.Width.get(). I'm hoping theres a better way than using mutexes to block BeginRender from returning until the scheduled Invoke() happens.
public unsafe sbyte* BeginRender()
{
Rectangle locked_area =
new Rectangle(0, 0, target_image.Width, target_image.Height);
target_data = target_image.LockBits(
locked_area,
System.Drawing.Imaging.ImageLockMode.WriteOnly,
target_image.PixelFormat);

IntPtr pixels = target_data.Scan0;
return (sbyte*)pixels;
}
public void EndRender()
{
target_image.UnlockBits(target_data);
pictureBox1.Invalidate();
}


Also, am I always safe calling Invalidate() from another thread? [Edited by - thedustbustr on July 3, 2008 9:01:35 AM]

##### Share on other sites
So let me get this straight. The order of operation is:

1) Thread A calls BeginRender() asynchronously (so another thread does the work).
2) Thread A does the actual rendering.
3) Thread A calls EndRender() asynchronously (so another thread does the work again).

And BeginThread() needs to finish before you can actually render, since it's in charge of locking the buffer. Plus, EndRender() can't be executed until you're done rendering since it unlocks the buffer. These three steps must always happen in that order and must finish one after another. Why are these operations being run in different threads?

##### Share on other sites
Maybe I explained poorly.

Two threads: the GUI thread, and a Work thread. The GUI thread registers callbacks with the work thread. The Work thread uses these callbacks to communicate with the GUI thread - to communicate required buffer size, to get a place to render, and to signal rendering finished.

-GUI thread creates a picture box, and an image, and provides callbacks to access the pixels of the image
-Work thread uses callback BeginRender() to get a pixel address, immediately writes to that address, when its done writing it uses callback EndRender() to signal that the pixels are updated, and to refresh the image.

Sooo:
1) Work thread synchronously calls BeginRender(), which locks the pixels. This call blocks.
2) Work thread renders to that buffer

Simultaneously, the GUI is doing GUI things and apparently if you resize the GUI it touches the image. so if the GUI thread handles a resize while the work thread is trying to lock the image, boom. "Asynchronous" as in asynchronous I/O might be the wrong word here, sorry if that caused confusion.

Its being done from a separate thread because, well, thats how I designed it for another application, and I don't have time to rewrite it for this application. I dont make any new threads from C# - I just register my callbacks, call library.connect(), and the library opens its own thread and goes on its merry way.

Quote:
 And BeginThread() needs to finish before you can actually render, since it's in charge of locking the buffer. Plus, EndRender() can't be executed until you're done rendering since it unlocks the buffer. These three steps must always happen in that order and must finish one after another. Why are these operations being run in different threads?

All of those statements are true. All of those operations happen synchronously (sequentially) in the Work thread. The crash occurs when the GUI gets resized in parallel with BeginRender() (after BeginRender finishes, theres no longer a conflict because the image is locked - so it takes a few seconds worth of continuous resizing to get the crash timing right)

If you think the design is suspect I'll likely post it for peer review.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628306
• Total Posts
2981944

• 10
• 11
• 11
• 11
• 10