Opened an instance of the assignment form?

I have a Windows form that opens another form. In its secondary form, it starts the task asynchronously. If the user starts the task and then cancels it and quickly closes the form, the form is Disposed and is null, but when the task returns due to cancellation, I still get a MessageBox.Show

public class MyMainForm : Form
{
  public void OpenChildForm()
  {
     MyChildForm form = new MyChildForm();
     form.ShowDialog();
     form.Dispose();
     form = null;
  }
}

public class MyChildForm : Form
{

  private CancellationTokenSource MyTokensource;
  private Task task; 


  public void StartTask()
  {
     MyTokensource = new CancellationTokenSource();
     task = Task.Factory.StartNew(() => MyMethod(MyTokensource.Token), MyTokensource.Token);
  }

  public void MyMethod(CancellationToken token)
  {
      var result = StaticClass.DoSomethingLengthy(token);  //The cancel make take a couple of seconds to return here
      if (result == Cancelled)
      {
         MessageBox.Show("Cancelled");
         UpdateLabel("Cancelled")
       }
  }

  public void ButtonClose_Click()
  { 
    if (task != null && !task.IsCompleted)
    {
      MyTokensource.Cancel();
    }
    this.Close();
  }
}

      

+3


source to share


5 answers


the form is Disposed and is null, but when the task returns after being canceled, I still get the MessageBox.Show message

Setting a variable that is a reference to a form to null, and even calling Dispose () on a form, does not actually destroy the form. The task is still running until canceled ( CancellationTokenSource

designed as a collaborative model for cancellation).



Thus, you need to explicitly handle the code path that occurs when the task is canceled. It can be as simple as checking if you have deleted yourself i.e.

if (this.IsDisposed)
    return; // Just break out if we canceled and shut down

// Your other code....
if (result == Cancelled)
    MessageBox.Show("Cancelled");

      

+2


source


It makes sense. Task

turns off when executed asynchronously, its execution time is not tied to lifetime Form

. You just need to add an explicit check to make sure you don't show MessageBox

if Form

has already been / has been removed:



if(result == Cancelled
            &&
   !(this.Disposing
           ||
    this.IsDisposed))
{
    MessageBox.Show("Cancelled");
}

      

+2


source


One more note: make sure you don't call StartTask()

more than once.

If so, you end up with multiple asynchronous tasks and multiple instances CancellationTokenSource

(of which only one of them still references the form).

+1


source


The form instance still exists, although the window may not be displayed. To make sure it MessageBox

doesn't show up after the form is closed, add an event to OnClosing

and set a member variablem_formClosed

to true

. Show message only when member variable false

.

if (result == Cancelled && !m_formClosed)
    MessageBox.Show("Cancelled");

      

0


source


The GC may not have collected the form even though you are calling Dispose()

and setting the reference to null. This is fine as GC is not deterministic.

Because of the way the implementation IDisposable

, you can check the properties IsDisposed

and IsDisposing

in the form to find out whether the method Dispose()

has already been called or is in progress.

0


source







All Articles