Solved

Blocking the calling thread when starting a new thread

Posted on 2004-08-25
21
192 Views
Last Modified: 2010-04-15
I want to start a seperate thread and block the calling thread until that thread has completed.  

I am doing this because I need to call a method that is uploading a lot of data and needs to be aborted under some situations.  I want the thread that makes this methodo call to block in the normal case when no abortion is neccessary.  I don't want to have to abort the calling thread in order to end the upload method because the calling thread needs to perform cleanup.  

What is the best way to do this?
0
Comment
Question by:jjacksn
  • 9
  • 8
  • 4
21 Comments
 
LVL 37

Expert Comment

by:gregoryyoung
Comment Utility
umm perhaps I am confused ... you want the calling thread to block until the child thread is completed and exits ...

why not just do the operation in the first thread ? you aren't gaining anything as far as concurrency if the first thread blocks the whole time ...

0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
I don't want it to be concurrent.  

But,the calling thread has to clean up some objects and display some output text.  The calling thread is calling a method in an object that has no idea when to abort (and no idea how to appropriately change the display).  I cannot just abort the calling thread because it has to cleanup objects.  It cleans up these objects before making the call to the 2nd method (in child thread), but I cannot safely just abort the calling thread because I don't know where it is in the execution process.  I am not doing this for concurrency, I am doing this for the ability to abort the child thread.  There is no easy way to simply cancel child method because it is making a remote call that could block for seconds.  

Isn't there something simple like

Thread.Wait(childThread)?
0
 
LVL 3

Expert Comment

by:gillgates
Comment Utility
Inside the calling thread...


you start your worker thread

Thread t = new thread(bla bla);
t.start();
t.join();  //This should block until t is done
0
 
LVL 3

Assisted Solution

by:gillgates
gillgates earned 200 total points
Comment Utility
Here is some same code.....



------------------------------------------


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

namespace threadblock
{
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
      {
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;

            public Form1()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();

                  //
                  // TODO: Add any constructor code after InitializeComponent call
                  //
            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #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()
            {
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(292, 266);
                  this.Name = "Form1";
                  this.Text = "Form1";
                  this.Load += new System.EventHandler(this.Form1_Load);

            }
            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                  Application.Run(new Form1());
            }

            private void Form1_Load(object sender, System.EventArgs e)
            {
                  temp mytemp = new temp();
                  Thread t = new Thread(new ThreadStart(mytemp.run));
                  t.Start();
            }
      }

      public class temp
      {
            public temp()
            {
                  
            }
            public void run()
            {
                  temp2 myt2;
                  myt2 = new temp2();
                  Thread t2 = new Thread(new ThreadStart(myt2.run));
                  t2.Start();
                  t2.Join();
                  MessageBox.Show("Parent");
            }
      }

      public class temp2
      {
            public temp2()
            {
                  
            }
            public void run()
            {
                  Thread.Sleep(10000);
                  MessageBox.Show("Child");
            }

      }
}
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
gillgates, I am having a problem,

I can join the thread fine.  

the child thread is making a remoting calling that takes several seconds to return, and this is what I am trying to avoid having to wait for.

When I call _childThread.Abort(), the thread that called join does not start executing immediatley.  The abort call still appears to wait for the Remote Method call to return, although the break point immediately after this line is not getting hit.

Does Abort wait for the current method being called to complete?  If so, what should be I doing rather than calling abort?  
0
 
LVL 37

Expert Comment

by:gregoryyoung
Comment Utility
you miss my point ... if you are starting a single thread from a thread and calling join() you are losing any gain you would be gaining by having a thread.
0
 
LVL 37

Expert Comment

by:gregoryyoung
Comment Utility
abort throws an Exception to your thread code.
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
gregory, as per you first post, I disagree, considering the following:  


long upload method
{

//DO SOME INIT and CLEANUP HERE including

CleaningMutex.WaitOne();
if(notcleaned)
{
//clean
}
CleaningMutix.ReleaseMutex();

_uploadThread = new Thread(new ThreadStart(UploadData));
_uploadThread.Start();
_uploadThread.Join();
_uploadThread = null;

//DO SOME STUFF2

}

now, I don't care if STUFF2 gets done (although it makes displaying the UI trickier, but that's not a big deal).  However, I CANNOT stop the cleanup from happening or bad stuff will occur.  

Therefore, I cannot just kill this method in the middle of its execution.  By struction it like this, I can then have

CancelMethod
{

if(_uploadThread != null)
         _uploadThread.Abort();
else if(_stuff_about_cleanup_not_being_done_)
{
CleaningMutex.WaitOne();
if(notcleaned)
{
//clean
}
CleaningMutix.ReleaseMutex();
}

If there is a better way to do this, I'm totally open to it, I just can't think of a way.  

Now, as per your second comment, why is this not causing the RemoteMethod to return right away?
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
I just checked more thoroughly, and it is definitely waiting for the Remoting method to complete before the Exception is generated in the thread.
0
 
LVL 37

Expert Comment

by:gregoryyoung
Comment Utility
ok..

you have thread1 which starts thread2 and then waits for it to finish, aside from the fact that you are spawning another thread what else are you gaining ?

There are other ways of handling timeouts.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 37

Expert Comment

by:gregoryyoung
Comment Utility
look at using asynchronous calls ...
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
the calling thread is already synchronous.  This entire setup is just to kill/return from the remote method call immediately, rather than waiting for it to complete.  If I wanted to wait for it to complete, I could just check a flag as soon as it returns.  

Why does abort wait for the Remote Method call to return?
0
 
LVL 3

Expert Comment

by:gillgates
Comment Utility
I am confused about what you are looking for.  Let me see if I have it.

You have a program that spawns thead "A" and you want theard "A" to spawn thread "b".  You then want thread "A" to wait until thread "b" is done?  


This is what I thought you wanted and to do this you would do a join() on thread "b".  But you say that you don't want to wait for thread "b" to finsh since "the child thread is making a remoting calling that takes several seconds to return, and this is what I am trying to avoid having to wait for."  So just don't do a Join() on thread "b" and thread "A" won't wait.  I am still confused.
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
gillgates, you are correct in your first interpretation, in the normal case.  

However, When I want to CANCEL the call, however, I want thread "B" do die immediately so that thread "A" can continue immediately.  The way it is now, when I call B.Abort(), it does not actually catch the ThreadAbortException and return control to "A" until after the Remote Method call returns.  

The main thread has a button that says cancel upload, and this is why it is neccessary.  I can't just kill off "A", because I don't know where in the execution of A it is and that can be dangerous.  I could solve this problem by putting a flag in the method that Thread "A" is running.  But, I am still going to be left with the problem that it doesn't die until after the remote method call has completed.  Which isn't a big problem but I want to know why it is happening.  
0
 
LVL 3

Expert Comment

by:gillgates
Comment Utility
in thread "b" you can....


thread b
{
   try
   {
      //your work
    }
    catch(System.Threading.ThreadInterruptedException E)
    {
         return;
    }
}

in thread A...

thread A
{
    try
    {
       b.Start();
       b.Join();
    }
    catch(System.Threading.ThreadInterruptedException E)
    {
        b.Interrupt();
    }
   
    //The rest of A's work.
}

in your main program
private void btnCancel_Click(object sender, System.EventArgs e)
{
    A.Interrup();
}



   

0
 
LVL 37

Accepted Solution

by:
gregoryyoung earned 300 total points
Comment Utility
jjaksn why don't you just handle it the way most protocols handle it  ...

as for the other suggestion

Interrupt  Restarts, or awakens, a sleeping thread and throws a ThreadInterruptedException in it (If the thread is not sleeping, the Interrupt is queued until the next Sleep operation.)

note sleep operation ...

http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemRuntimeRemotingMessagingIMessageSinkClassAsyncProcessMessageTopic.asp you will see it returns an IMessageCtrl http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimeremotingmessagingimessagectrlclasscanceltopic.asp this object has a cancel method ... much easier than doing all of this yourself.
0
 
LVL 37

Expert Comment

by:gregoryyoung
Comment Utility
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconinvokingwebservicesasynchronously.asp gives an example with a web service they also discuss how to use the cancel functionality using remoting instead would be fairly easy.
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
The problem with the asynchronous calls is that then I would hammer the server.

I might have 2000 things to upload, each upload of 50 takes lets say, 10 seconds.  If I do it asynchrounosly, then I will hammer the server with 40 requests in a matter of seconds.  

I want each single user/machine to upload the 50 sequentially (not that it matters for the client side, but I don't want one user to hog the server resources).  

the current structure of the upload method is:

select all rows that need to be send
while true()
{
upload 50 at at time until done
break
}

I could use async calls, and send the next 50 in the Callback function, but I think that is uglier than my current idea.  not that either is overly elegant.
0
 
LVL 37

Expert Comment

by:gregoryyoung
Comment Utility
yes but cancelling the async call is quite easy ;)
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
true, I didn't see that until after that post.  I will look into it.  
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
There was just no good way to do that.  I ended up leaving the architecture basically the way it was with the 2 threads and moving the UI display code elsewhere.  The main problem was that to use Callbacks and delegates, (which was nice), the code/class got really ugly in terms of keeping track of where you were at in the upload process each time.  

At any rate, thanks everyone.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Extention Methods in C# 3.0 by Ivo Stoykov C# 3.0 offers extension methods. They allow extending existing classes without changing the class's source code or relying on inheritance. These are static methods invoked as instance method. This…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now