private void threadEntryPoint()
        {
            //do a bunch of stuff

            //when you are done:
            //initialize object with data that you want to return
            DataYouWantToReturn dataYouWantToReturn = new DataYouWantToReturn();

            dataYouWantToReturn.someProperty = "more data";

            //signal completion by firing an event
            OnThread1Completed(new AsyncCompletedEventArgs(null, false, dataYouWantToReturn));
        }
 void thread1_Thread1Completed(object sender, AsyncCompletedEventArgs e)
 {
     if (this.InvokeRequired)
     {    //marshal the call if we are not on the GUI thread
         BeginInvoke(new AsyncCompletedEventHandler(thread1_Thread1Completed),
                     new object[] { sender, e });
     }
     else
     {
         //display error if error occurred
         //if no error occurred, process data
         if (e.Error == null)
         {    //then success
             MessageBox.Show("Worker thread completed successfully");
             DataYouWantToReturn someData = e.UserState as DataYouWantToReturn;
             MessageBox.Show("Your data my lord: " + someData.someProperty);
         }
         else    //error
         {
             MessageBox.Show("The following error occurred:" + Environment.NewLine + e.Error.ToString());
         }
     }
 }