Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing Form closure from freezing Invoke calls

Tags:

c#

winforms

In my application I've created a thread which draws on a Bitmap object, and when it is done drawing it calls form.Invoke(form.Refresh) which draws the bitmap to the main form. (form being a reference to the main form of my application.)

The Problem: I've noticed that if I close the form while the other thread is waiting for the callback message from UI thread (because of the Invoke call) - the thread will wait indefinitely(?) and will essentially get stuck, preventing the application from closing.

Using BeginInvoke doesn't make sense in my program, because the time it takes to refresh the form has to be accounted for in the work of the thread.

Q: What would be the best way to prevent this from happening?

Edit: I've read in some places that its a bad idea, but it seems to me that the only way to deal with this is to call Thread.Abort(). I can't close the thread by using a flag or something similar, since its just stuck at the Invoke call.

Edit 2: To make it clear, what I'm looking for is a way to tell the worker thread that it should stop waiting for the Invoke callback and continue working.

like image 500
Acidic Avatar asked Dec 06 '25 14:12

Acidic


1 Answers

The best answer is of course to use BeginInvoke. If you need the thread to wait until the UI thread has processed the result, then you'll have to add another synchronization method to the process.

An AutoResetEvent would work as a gate, something like this:

using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

public class MainForm : Form
{
    protected override void OnLoad(EventArgs e)
    {
        new Thread(ProcessBitmap) { IsBackground = true }.Start(null);
        base.OnLoad(e);
    }

    void DoneProcessingBitmap(Bitmap bitmap)
    {
        Trace.WriteLine("Done Processing Bitmap");
        uiDoneEvent.Set();
    }

    AutoResetEvent uiDoneEvent = new AutoResetEvent(false);
    volatile bool terminate = false;

    void ProcessBitmap(object state)
    {
        while (!terminate)
        {
            Bitmap bitmap = (Bitmap)state;
            Trace.WriteLine("Processing Bitmap");
            Thread.Sleep(5000); // simulate processing
            BeginInvoke(new Action<Bitmap>(DoneProcessingBitmap), bitmap);
            Trace.WriteLine("Waiting");
            uiDoneEvent.WaitOne();
        }
    }

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }
}
like image 139
Tergiver Avatar answered Dec 08 '25 02:12

Tergiver



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!