AsyncCallback called twice on Exception

  • Thread starter Thread starter Craig Vermeer
  • Start date Start date
C

Craig Vermeer

Hi All,

I noticed an interesting issue the other day, and thought someone here
might be able to shed some light on things.

I have a situation where I'm using asynchronous delegates, and an
exception is getting thrown from within the AsyncCallback on the
delegate. For some reason, this causes the AsyncCallback delegate to be
executed twice. Now, I understand how to stop the situation from
happening. However, what I didn't know was why things behaved the way
they did.

Below is a 'short but complete' code sample that demonstrates the behavior.

Thanks,
Craig



using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace AyncDelegateIssueDemo
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
private delegate void TestHandler(string message);
private event TestHandler CallbackEvent;
private event EventHandler AsyncEvent;

public Form1()
{
InitializeComponent();
AsyncEvent += new EventHandler(Form1_AsyncEvent);
AsyncEvent.BeginInvoke(this, EventArgs.Empty, new
AsyncCallback(OnAsyncCompleted), AsyncEvent);
CallbackEvent += new TestHandler(Form1_CallbackEvent);
}

private void OnAsyncCompleted(IAsyncResult res)
{
string message = "done";
try
{
((EventHandler)res.AsyncState).EndInvoke(res);
}
catch(Exception ex){message = ex.Message;}
Invoke(CallbackEvent, new object[]{message});
throw new Exception("test");
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBox1.Location = new System.Drawing.Point(0, 0);
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(292, 273);
this.textBox1.TabIndex = 0;
this.textBox1.Text = "";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.textBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion

[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void Form1_AsyncEvent(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(1000);
}

private void Form1_CallbackEvent(string message)
{
this.textBox1.Text += (message + Environment.NewLine);
}
}
}
 
Back
Top