Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 207
  • Last Modified:

Blocking the calling thread when starting a new thread

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
jjacksn
Asked:
jjacksn
  • 9
  • 8
  • 4
2 Solutions
 
gregoryyoungCommented:
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
 
jjacksnAuthor Commented:
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
 
gillgatesCommented:
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
What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

 
gillgatesCommented:
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
 
jjacksnAuthor Commented:
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
 
gregoryyoungCommented:
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
 
gregoryyoungCommented:
abort throws an Exception to your thread code.
0
 
jjacksnAuthor Commented:
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
 
jjacksnAuthor Commented:
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
 
gregoryyoungCommented:
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
 
gregoryyoungCommented:
look at using asynchronous calls ...
0
 
jjacksnAuthor Commented:
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
 
gillgatesCommented:
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
 
jjacksnAuthor Commented:
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
 
gillgatesCommented:
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
 
gregoryyoungCommented:
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
 
gregoryyoungCommented:
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
 
jjacksnAuthor Commented:
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
 
gregoryyoungCommented:
yes but cancelling the async call is quite easy ;)
0
 
jjacksnAuthor Commented:
true, I didn't see that until after that post.  I will look into it.  
0
 
jjacksnAuthor Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 9
  • 8
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now