Calling Win32 TerminateThread() via unmanaged code

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Bryan

    Calling Win32 TerminateThread() via unmanaged code

    I have a multi-threaded C# console application that uses WMI
    (System.Managem ent namespace) to make RPC calls to several servers (600+ )
    and returns ScheduledJobs. The section of my code that performs the query
    is contained in a delegate function that I execute via a second thread. On 1
    or 2 of the 600+ servers the query hangs. I've tried to use Thread.Join()
    coupled with a Thread.Abort() but this does not kill the thread.

    Based on other post I've read this is a common occurrence and the only way
    to kill this thread is to use TerminateThread () located in the Kernel32.dll.
    I'm not really sure how to call this unmanaged code. Also TerminateThread ()
    requires the thread's handle and I'm not sure how to obtain this in .NET.
    I've made a "best guess" at the code but it doesn't work. See sample below.
    Can anyone give me a code sample of how this can be done? This is my first
    multi-threaded application and I'm pretty much a newbie to unmanaged code.

    // This class allows me to pass a server name to the function
    // and still call it as a delegate.

    public class Parcer
    {
    public int ThreadID;
    private string Server;
    public DataSet ds;
    public Parcer(string Server)
    {
    this.Server = Server;
    }

    public void ParceJobs()
    {
    ThreadID = AppDomain.GetCu rrentThreadId() ;
    IntelJobReader JobReader = new IntelJobReader( ); //Instanciate the
    JobReader object. This is a class I wrote that make the WMI calls and
    returns a DataSet.
    DataSet JobSchedules = ( DataSet ) ( JobReader.GetSv rJobs(Server) );
    this.ds = JobSchedules;
    }
    }

    // This is my best guess at the unmanaged code. It runs without error but
    does not terminate the thread.

    public class Win32
    {
    [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
    public static extern int TerminateThread (int hThread);
    }

    // Excerpt from my Conseole App's Main code:

    Parcer SchJobs = new Parcer(Server);
    Thread JobTimeout = new Thread(new ThreadStart(Sch Jobs.ParceJobs) );
    JobTimeout.Star t();
    JobTimeout.Join (10000);
    if (!JobTimeout.Jo in(10000))
    {
    JobTimeout.Abor t(); // This will not terminate the thread
    Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
    Console.WriteLi ne("The thread timed out no change will be made to the
    DB");
    }

    Thanks,
    Bryan


  • Dmitriy Lapshin [C# / .NET MVP]

    #2
    Re: Calling Win32 TerminateThread () via unmanaged code

    > On 1 or 2 of the 600+ servers the query hangs. I've tried to use
    Thread.Join()[color=blue]
    > coupled with a Thread.Abort() but this does not kill the thread.[/color]

    Ensure the sequence was Thread.Abort() first and then Thread.Join(), not the
    other way around.
    Calling Thread.Join() first will result in a deadlock you are probably
    experiencing.

    As for the TerminateThread , this API function has two parameters (the second
    one is also int), but I am not sure how one can obtain the handle of the
    thread. You might need to resort to the GetCurrentThrea d() API to do that.

    --
    Dmitriy Lapshin [C# / .NET MVP]
    X-Unity Test Studio

    Bring the power of unit testing to VS .NET IDE

    "Bryan" <techie77@veriz on.net> wrote in message
    news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...[color=blue]
    > I have a multi-threaded C# console application that uses WMI
    > (System.Managem ent namespace) to make RPC calls to several servers (600+ )
    > and returns ScheduledJobs. The section of my code that performs the query
    > is contained in a delegate function that I execute via a second thread. On[/color]
    1[color=blue]
    > or 2 of the 600+ servers the query hangs. I've tried to use Thread.Join()
    > coupled with a Thread.Abort() but this does not kill the thread.
    >
    > Based on other post I've read this is a common occurrence and the only way
    > to kill this thread is to use TerminateThread () located in the[/color]
    Kernel32.dll.[color=blue]
    > I'm not really sure how to call this unmanaged code. Also[/color]
    TerminateThread ()[color=blue]
    > requires the thread's handle and I'm not sure how to obtain this in .NET.
    > I've made a "best guess" at the code but it doesn't work. See sample[/color]
    below.[color=blue]
    > Can anyone give me a code sample of how this can be done? This is my[/color]
    first[color=blue]
    > multi-threaded application and I'm pretty much a newbie to unmanaged code.
    >
    > // This class allows me to pass a server name to the function
    > // and still call it as a delegate.
    >
    > public class Parcer
    > {
    > public int ThreadID;
    > private string Server;
    > public DataSet ds;
    > public Parcer(string Server)
    > {
    > this.Server = Server;
    > }
    >
    > public void ParceJobs()
    > {
    > ThreadID = AppDomain.GetCu rrentThreadId() ;
    > IntelJobReader JobReader = new IntelJobReader( ); //Instanciate the
    > JobReader object. This is a class I wrote that make the WMI calls and
    > returns a DataSet.
    > DataSet JobSchedules = ( DataSet ) ([/color]
    JobReader.GetSv rJobs(Server) );[color=blue]
    > this.ds = JobSchedules;
    > }
    > }
    >
    > // This is my best guess at the unmanaged code. It runs without error but
    > does not terminate the thread.
    >
    > public class Win32
    > {
    > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
    > public static extern int TerminateThread (int hThread);
    > }
    >
    > // Excerpt from my Conseole App's Main code:
    >
    > Parcer SchJobs = new Parcer(Server);
    > Thread JobTimeout = new Thread(new ThreadStart(Sch Jobs.ParceJobs) );
    > JobTimeout.Star t();
    > JobTimeout.Join (10000);
    > if (!JobTimeout.Jo in(10000))
    > {
    > JobTimeout.Abor t(); // This will not terminate the thread
    > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
    > Console.WriteLi ne("The thread timed out no change will be made to the
    > DB");
    > }
    >
    > Thanks,
    > Bryan
    >
    >[/color]

    Comment

    • Willy Denoyette [MVP]

      #3
      Re: Calling Win32 TerminateThread () via unmanaged code

      You should never call ThreadTerminate , it will corrupt the process, or
      worse, if called while it holds a lock on the OS heap, all other threads in
      the system trying to allocate/free memory blocks from the same heap will
      block forever.
      Calling Thread.Abort() from another thread (asynch.) is also problematic:
      1. When the thread is blocked in unmanaged code, Abort will suspend until a
      return from unmanaged code is done and a safe point for GC is reached.
      2. Asynchronous Thread.Abort's should be deferred when executing a finally
      clause, this is not done in v1.1, possibly resulting in resource leaks and
      corrupted state.

      I would suggest you revise the portion of your "Management/WMI" code, IMO
      the solution should be found in there as it's the source of the problem
      (blocking thread).
      Another point to check is whether your code runs on a MTA thread (see
      MTA/STAThread attribute on Main), too many people get bitten by this.

      Willy.


      "Bryan" <techie77@veriz on.net> wrote in message
      news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...[color=blue]
      > I have a multi-threaded C# console application that uses WMI
      > (System.Managem ent namespace) to make RPC calls to several servers (600+ )
      > and returns ScheduledJobs. The section of my code that performs the query
      > is contained in a delegate function that I execute via a second thread. On[/color]
      1[color=blue]
      > or 2 of the 600+ servers the query hangs. I've tried to use Thread.Join()
      > coupled with a Thread.Abort() but this does not kill the thread.
      >
      > Based on other post I've read this is a common occurrence and the only way
      > to kill this thread is to use TerminateThread () located in the[/color]
      Kernel32.dll.[color=blue]
      > I'm not really sure how to call this unmanaged code. Also[/color]
      TerminateThread ()[color=blue]
      > requires the thread's handle and I'm not sure how to obtain this in .NET.
      > I've made a "best guess" at the code but it doesn't work. See sample[/color]
      below.[color=blue]
      > Can anyone give me a code sample of how this can be done? This is my[/color]
      first[color=blue]
      > multi-threaded application and I'm pretty much a newbie to unmanaged code.[/color]
      [color=blue]
      >
      > // This class allows me to pass a server name to the function
      > // and still call it as a delegate.
      >
      > public class Parcer
      > {
      > public int ThreadID;
      > private string Server;
      > public DataSet ds;
      > public Parcer(string Server)
      > {
      > this.Server = Server;
      > }
      >
      > public void ParceJobs()
      > {
      > ThreadID = AppDomain.GetCu rrentThreadId() ;
      > IntelJobReader JobReader = new IntelJobReader( ); //Instanciate the
      > JobReader object. This is a class I wrote that make the WMI calls and
      > returns a DataSet.
      > DataSet JobSchedules = ( DataSet ) ([/color]
      JobReader.GetSv rJobs(Server) );[color=blue]
      > this.ds = JobSchedules;
      > }
      > }
      >
      > // This is my best guess at the unmanaged code. It runs without error but
      > does not terminate the thread.
      >
      > public class Win32
      > {
      > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
      > public static extern int TerminateThread (int hThread);
      > }
      >
      > // Excerpt from my Conseole App's Main code:
      >
      > Parcer SchJobs = new Parcer(Server);
      > Thread JobTimeout = new Thread(new ThreadStart(Sch Jobs.ParceJobs) );
      > JobTimeout.Star t();
      > JobTimeout.Join (10000);
      > if (!JobTimeout.Jo in(10000))
      > {
      > JobTimeout.Abor t(); // This will not terminate the thread
      > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
      > Console.WriteLi ne("The thread timed out no change will be made to the
      > DB");
      > }
      >
      > Thanks,
      > Bryan
      >
      >[/color]


      Comment

      • Dmitriy Lapshin [C# / .NET MVP]

        #4
        Re: Calling Win32 TerminateThread () via unmanaged code

        Hello Willy,
        [color=blue]
        > Another point to check is whether your code runs on a MTA thread (see
        > MTA/STAThread attribute on Main), too many people get bitten by this.[/color]

        Could you please elaborate on this? I know what is STA and what is MTA, but
        how does it related to aborting a worker thread?

        --
        Dmitriy Lapshin [C# / .NET MVP]
        X-Unity Test Studio

        Bring the power of unit testing to VS .NET IDE

        "Willy Denoyette [MVP]" <willy.denoyett e@pandora.be> wrote in message
        news:OtV0jwxuDH A.2180@TK2MSFTN GP09.phx.gbl...[color=blue]
        > You should never call ThreadTerminate , it will corrupt the process, or
        > worse, if called while it holds a lock on the OS heap, all other threads[/color]
        in[color=blue]
        > the system trying to allocate/free memory blocks from the same heap will
        > block forever.
        > Calling Thread.Abort() from another thread (asynch.) is also problematic:
        > 1. When the thread is blocked in unmanaged code, Abort will suspend until[/color]
        a[color=blue]
        > return from unmanaged code is done and a safe point for GC is reached.
        > 2. Asynchronous Thread.Abort's should be deferred when executing a finally
        > clause, this is not done in v1.1, possibly resulting in resource leaks and
        > corrupted state.
        >
        > I would suggest you revise the portion of your "Management/WMI" code, IMO
        > the solution should be found in there as it's the source of the problem
        > (blocking thread).
        > Another point to check is whether your code runs on a MTA thread (see
        > MTA/STAThread attribute on Main), too many people get bitten by this.
        >
        > Willy.
        >
        >
        > "Bryan" <techie77@veriz on.net> wrote in message
        > news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...[color=green]
        > > I have a multi-threaded C# console application that uses WMI
        > > (System.Managem ent namespace) to make RPC calls to several servers[/color][/color]
        (600+ )[color=blue][color=green]
        > > and returns ScheduledJobs. The section of my code that performs the[/color][/color]
        query[color=blue][color=green]
        > > is contained in a delegate function that I execute via a second thread.[/color][/color]
        On[color=blue]
        > 1[color=green]
        > > or 2 of the 600+ servers the query hangs. I've tried to use[/color][/color]
        Thread.Join()[color=blue][color=green]
        > > coupled with a Thread.Abort() but this does not kill the thread.
        > >
        > > Based on other post I've read this is a common occurrence and the only[/color][/color]
        way[color=blue][color=green]
        > > to kill this thread is to use TerminateThread () located in the[/color]
        > Kernel32.dll.[color=green]
        > > I'm not really sure how to call this unmanaged code. Also[/color]
        > TerminateThread ()[color=green]
        > > requires the thread's handle and I'm not sure how to obtain this in[/color][/color]
        ..NET.[color=blue][color=green]
        > > I've made a "best guess" at the code but it doesn't work. See sample[/color]
        > below.[color=green]
        > > Can anyone give me a code sample of how this can be done? This is my[/color]
        > first[color=green]
        > > multi-threaded application and I'm pretty much a newbie to unmanaged[/color][/color]
        code.[color=blue]
        >[color=green]
        > >
        > > // This class allows me to pass a server name to the function
        > > // and still call it as a delegate.
        > >
        > > public class Parcer
        > > {
        > > public int ThreadID;
        > > private string Server;
        > > public DataSet ds;
        > > public Parcer(string Server)
        > > {
        > > this.Server = Server;
        > > }
        > >
        > > public void ParceJobs()
        > > {
        > > ThreadID = AppDomain.GetCu rrentThreadId() ;
        > > IntelJobReader JobReader = new IntelJobReader( ); //Instanciate[/color][/color]
        the[color=blue][color=green]
        > > JobReader object. This is a class I wrote that make the WMI calls and
        > > returns a DataSet.
        > > DataSet JobSchedules = ( DataSet ) ([/color]
        > JobReader.GetSv rJobs(Server) );[color=green]
        > > this.ds = JobSchedules;
        > > }
        > > }
        > >
        > > // This is my best guess at the unmanaged code. It runs without error[/color][/color]
        but[color=blue][color=green]
        > > does not terminate the thread.
        > >
        > > public class Win32
        > > {
        > > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
        > > public static extern int TerminateThread (int hThread);
        > > }
        > >
        > > // Excerpt from my Conseole App's Main code:
        > >
        > > Parcer SchJobs = new Parcer(Server);
        > > Thread JobTimeout = new Thread(new ThreadStart(Sch Jobs.ParceJobs) );
        > > JobTimeout.Star t();
        > > JobTimeout.Join (10000);
        > > if (!JobTimeout.Jo in(10000))
        > > {
        > > JobTimeout.Abor t(); // This will not terminate the thread
        > > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
        > > Console.WriteLi ne("The thread timed out no change will be made to[/color][/color]
        the[color=blue][color=green]
        > > DB");
        > > }
        > >
        > > Thanks,
        > > Bryan
        > >
        > >[/color]
        >
        >[/color]

        Comment

        • Bryan

          #5
          Re: Calling Win32 TerminateThread () via unmanaged code

          Thanks for the reply. I do call the Abort before the Join however the
          thread still hangs. Any idea how I can create the pointer to the thread and
          call TerminateThread ()?



          "Dmitriy Lapshin [C# / .NET MVP]" <x-code@no-spam-please.hotpop.c om> wrote
          in message news:upmtIewuDH A.1744@TK2MSFTN GP12.phx.gbl...[color=blue][color=green]
          > > On 1 or 2 of the 600+ servers the query hangs. I've tried to use[/color]
          > Thread.Join()[color=green]
          > > coupled with a Thread.Abort() but this does not kill the thread.[/color]
          >
          > Ensure the sequence was Thread.Abort() first and then Thread.Join(), not[/color]
          the[color=blue]
          > other way around.
          > Calling Thread.Join() first will result in a deadlock you are probably
          > experiencing.
          >
          > As for the TerminateThread , this API function has two parameters (the[/color]
          second[color=blue]
          > one is also int), but I am not sure how one can obtain the handle of the
          > thread. You might need to resort to the GetCurrentThrea d() API to do that.
          >
          > --
          > Dmitriy Lapshin [C# / .NET MVP]
          > X-Unity Test Studio
          > http://x-unity.miik.com.ua/teststudio.aspx
          > Bring the power of unit testing to VS .NET IDE
          >
          > "Bryan" <techie77@veriz on.net> wrote in message
          > news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...[color=green]
          > > I have a multi-threaded C# console application that uses WMI
          > > (System.Managem ent namespace) to make RPC calls to several servers[/color][/color]
          (600+ )[color=blue][color=green]
          > > and returns ScheduledJobs. The section of my code that performs the[/color][/color]
          query[color=blue][color=green]
          > > is contained in a delegate function that I execute via a second thread.[/color][/color]
          On[color=blue]
          > 1[color=green]
          > > or 2 of the 600+ servers the query hangs. I've tried to use[/color][/color]
          Thread.Join()[color=blue][color=green]
          > > coupled with a Thread.Abort() but this does not kill the thread.
          > >
          > > Based on other post I've read this is a common occurrence and the only[/color][/color]
          way[color=blue][color=green]
          > > to kill this thread is to use TerminateThread () located in the[/color]
          > Kernel32.dll.[color=green]
          > > I'm not really sure how to call this unmanaged code. Also[/color]
          > TerminateThread ()[color=green]
          > > requires the thread's handle and I'm not sure how to obtain this in[/color][/color]
          ..NET.[color=blue][color=green]
          > > I've made a "best guess" at the code but it doesn't work. See sample[/color]
          > below.[color=green]
          > > Can anyone give me a code sample of how this can be done? This is my[/color]
          > first[color=green]
          > > multi-threaded application and I'm pretty much a newbie to unmanaged[/color][/color]
          code.[color=blue][color=green]
          > >
          > > // This class allows me to pass a server name to the function
          > > // and still call it as a delegate.
          > >
          > > public class Parcer
          > > {
          > > public int ThreadID;
          > > private string Server;
          > > public DataSet ds;
          > > public Parcer(string Server)
          > > {
          > > this.Server = Server;
          > > }
          > >
          > > public void ParceJobs()
          > > {
          > > ThreadID = AppDomain.GetCu rrentThreadId() ;
          > > IntelJobReader JobReader = new IntelJobReader( ); //Instanciate[/color][/color]
          the[color=blue][color=green]
          > > JobReader object. This is a class I wrote that make the WMI calls and
          > > returns a DataSet.
          > > DataSet JobSchedules = ( DataSet ) ([/color]
          > JobReader.GetSv rJobs(Server) );[color=green]
          > > this.ds = JobSchedules;
          > > }
          > > }
          > >
          > > // This is my best guess at the unmanaged code. It runs without error[/color][/color]
          but[color=blue][color=green]
          > > does not terminate the thread.
          > >
          > > public class Win32
          > > {
          > > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
          > > public static extern int TerminateThread (int hThread);
          > > }
          > >
          > > // Excerpt from my Conseole App's Main code:
          > >
          > > Parcer SchJobs = new Parcer(Server);
          > > Thread JobTimeout = new Thread(new ThreadStart(Sch Jobs.ParceJobs) );
          > > JobTimeout.Star t();
          > > JobTimeout.Join (10000);
          > > if (!JobTimeout.Jo in(10000))
          > > {
          > > JobTimeout.Abor t(); // This will not terminate the thread
          > > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
          > > Console.WriteLi ne("The thread timed out no change will be made to[/color][/color]
          the[color=blue][color=green]
          > > DB");
          > > }
          > >
          > > Thanks,
          > > Bryan
          > >
          > >[/color]
          >[/color]


          Comment

          • Dave

            #6
            Re: Calling Win32 TerminateThread () via unmanaged code

            Calling TerminateThread will not do what you want it to do. Even if you were
            able to kill the underlying OS thread the CLR will not "know" that you did
            this and so the CLR's managed thread would still be waiting (forever) for
            the unmanaged thread to return back to the managed world.

            In addition, killing an OS thread has LOTS of side-effects; its stack never
            gets deallocated, mutexes and critical sections it owns never get released
            etc. Unless your own code controls the thread (setting up its own restricted
            environment so that it cannot allocate a system resource that requires
            cleanup) it is very dangerous to do this. Even in Win32 land the docs warn
            you to only do this as an asbolute last resort. Based on your sample code
            there's nothing there that appears to be of such a mission critical nature
            that this is required.

            IMO this is one of the areas in .NET that is not completely baked. It's done
            well enough that you want to do use it but there really isn't enough control
            over the execution model that you can reliably control other threads. This
            is especially noticable in the case you've run into, that of P/Invoking to
            an unmanaged API that hangs.

            An option you can take all the code that p/invokes and may hang and remote
            it from another appdomain. When you want to terminate all those threads
            unload the appdomain. I've noticed that the runtime does a better job of
            unwinding all those threads when it unloads an appdomain then when you
            simply try to abort the thread. Make sure you mark all those threads as
            background.


            "Bryan" <techie77@veriz on.net> wrote in message
            news:RscAb.1302 $%01.238@nwrddc 02.gnilink.net. ..[color=blue]
            > Thanks for the reply. I do call the Abort before the Join however the
            > thread still hangs. Any idea how I can create the pointer to the thread[/color]
            and[color=blue]
            > call TerminateThread ()?
            >
            >
            >
            > "Dmitriy Lapshin [C# / .NET MVP]" <x-code@no-spam-please.hotpop.c om> wrote
            > in message news:upmtIewuDH A.1744@TK2MSFTN GP12.phx.gbl...[color=green][color=darkred]
            > > > On 1 or 2 of the 600+ servers the query hangs. I've tried to use[/color]
            > > Thread.Join()[color=darkred]
            > > > coupled with a Thread.Abort() but this does not kill the thread.[/color]
            > >
            > > Ensure the sequence was Thread.Abort() first and then Thread.Join(), not[/color]
            > the[color=green]
            > > other way around.
            > > Calling Thread.Join() first will result in a deadlock you are probably
            > > experiencing.
            > >
            > > As for the TerminateThread , this API function has two parameters (the[/color]
            > second[color=green]
            > > one is also int), but I am not sure how one can obtain the handle of the
            > > thread. You might need to resort to the GetCurrentThrea d() API to do[/color][/color]
            that.[color=blue][color=green]
            > >
            > > --
            > > Dmitriy Lapshin [C# / .NET MVP]
            > > X-Unity Test Studio
            > > http://x-unity.miik.com.ua/teststudio.aspx
            > > Bring the power of unit testing to VS .NET IDE
            > >
            > > "Bryan" <techie77@veriz on.net> wrote in message
            > > news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...[color=darkred]
            > > > I have a multi-threaded C# console application that uses WMI
            > > > (System.Managem ent namespace) to make RPC calls to several servers[/color][/color]
            > (600+ )[color=green][color=darkred]
            > > > and returns ScheduledJobs. The section of my code that performs the[/color][/color]
            > query[color=green][color=darkred]
            > > > is contained in a delegate function that I execute via a second[/color][/color][/color]
            thread.[color=blue]
            > On[color=green]
            > > 1[color=darkred]
            > > > or 2 of the 600+ servers the query hangs. I've tried to use[/color][/color]
            > Thread.Join()[color=green][color=darkred]
            > > > coupled with a Thread.Abort() but this does not kill the thread.
            > > >
            > > > Based on other post I've read this is a common occurrence and the only[/color][/color]
            > way[color=green][color=darkred]
            > > > to kill this thread is to use TerminateThread () located in the[/color]
            > > Kernel32.dll.[color=darkred]
            > > > I'm not really sure how to call this unmanaged code. Also[/color]
            > > TerminateThread ()[color=darkred]
            > > > requires the thread's handle and I'm not sure how to obtain this in[/color][/color]
            > .NET.[color=green][color=darkred]
            > > > I've made a "best guess" at the code but it doesn't work. See sample[/color]
            > > below.[color=darkred]
            > > > Can anyone give me a code sample of how this can be done? This is my[/color]
            > > first[color=darkred]
            > > > multi-threaded application and I'm pretty much a newbie to unmanaged[/color][/color]
            > code.[color=green][color=darkred]
            > > >
            > > > // This class allows me to pass a server name to the function
            > > > // and still call it as a delegate.
            > > >
            > > > public class Parcer
            > > > {
            > > > public int ThreadID;
            > > > private string Server;
            > > > public DataSet ds;
            > > > public Parcer(string Server)
            > > > {
            > > > this.Server = Server;
            > > > }
            > > >
            > > > public void ParceJobs()
            > > > {
            > > > ThreadID = AppDomain.GetCu rrentThreadId() ;
            > > > IntelJobReader JobReader = new IntelJobReader( ); //Instanciate[/color][/color]
            > the[color=green][color=darkred]
            > > > JobReader object. This is a class I wrote that make the WMI calls and
            > > > returns a DataSet.
            > > > DataSet JobSchedules = ( DataSet ) ([/color]
            > > JobReader.GetSv rJobs(Server) );[color=darkred]
            > > > this.ds = JobSchedules;
            > > > }
            > > > }
            > > >
            > > > // This is my best guess at the unmanaged code. It runs without error[/color][/color]
            > but[color=green][color=darkred]
            > > > does not terminate the thread.
            > > >
            > > > public class Win32
            > > > {
            > > > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
            > > > public static extern int TerminateThread (int hThread);
            > > > }
            > > >
            > > > // Excerpt from my Conseole App's Main code:
            > > >
            > > > Parcer SchJobs = new Parcer(Server);
            > > > Thread JobTimeout = new Thread(new ThreadStart(Sch Jobs.ParceJobs) );
            > > > JobTimeout.Star t();
            > > > JobTimeout.Join (10000);
            > > > if (!JobTimeout.Jo in(10000))
            > > > {
            > > > JobTimeout.Abor t(); // This will not terminate the thread
            > > > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
            > > > Console.WriteLi ne("The thread timed out no change will be made to[/color][/color]
            > the[color=green][color=darkred]
            > > > DB");
            > > > }
            > > >
            > > > Thanks,
            > > > Bryan
            > > >
            > > >[/color]
            > >[/color]
            >
            >[/color]


            Comment

            • Willy Denoyette [MVP]

              #7
              Re: Calling Win32 TerminateThread () via unmanaged code

              It doesn't relate, my point was to forget about aborting a thread
              asynchronously.
              IMO, OP should take a look at the WMI related code, maybe WMI calls could be
              done asynchronously i.s.o synchronously (blocking), that way you don't have
              to try to abort a blocked thread (something that doesn't work after all,
              unless by calling ThreadTerminate ).

              Willy.


              "Dmitriy Lapshin [C# / .NET MVP]" <x-code@no-spam-please.hotpop.c om> wrote
              in message news:uFkPD4yuDH A.2224@TK2MSFTN GP10.phx.gbl...[color=blue]
              > Hello Willy,
              >[color=green]
              > > Another point to check is whether your code runs on a MTA thread (see
              > > MTA/STAThread attribute on Main), too many people get bitten by this.[/color]
              >
              > Could you please elaborate on this? I know what is STA and what is MTA,[/color]
              but[color=blue]
              > how does it related to aborting a worker thread?
              >
              > --
              > Dmitriy Lapshin [C# / .NET MVP]
              > X-Unity Test Studio
              > http://x-unity.miik.com.ua/teststudio.aspx
              > Bring the power of unit testing to VS .NET IDE
              >
              > "Willy Denoyette [MVP]" <willy.denoyett e@pandora.be> wrote in message
              > news:OtV0jwxuDH A.2180@TK2MSFTN GP09.phx.gbl...[color=green]
              > > You should never call ThreadTerminate , it will corrupt the process, or
              > > worse, if called while it holds a lock on the OS heap, all other threads[/color]
              > in[color=green]
              > > the system trying to allocate/free memory blocks from the same heap will
              > > block forever.
              > > Calling Thread.Abort() from another thread (asynch.) is also[/color][/color]
              problematic:[color=blue][color=green]
              > > 1. When the thread is blocked in unmanaged code, Abort will suspend[/color][/color]
              until[color=blue]
              > a[color=green]
              > > return from unmanaged code is done and a safe point for GC is reached.
              > > 2. Asynchronous Thread.Abort's should be deferred when executing a[/color][/color]
              finally[color=blue][color=green]
              > > clause, this is not done in v1.1, possibly resulting in resource leaks[/color][/color]
              and[color=blue][color=green]
              > > corrupted state.
              > >
              > > I would suggest you revise the portion of your "Management/WMI" code,[/color][/color]
              IMO[color=blue][color=green]
              > > the solution should be found in there as it's the source of the problem
              > > (blocking thread).
              > > Another point to check is whether your code runs on a MTA thread (see
              > > MTA/STAThread attribute on Main), too many people get bitten by this.
              > >
              > > Willy.
              > >
              > >
              > > "Bryan" <techie77@veriz on.net> wrote in message
              > > news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...[color=darkred]
              > > > I have a multi-threaded C# console application that uses WMI
              > > > (System.Managem ent namespace) to make RPC calls to several servers[/color][/color]
              > (600+ )[color=green][color=darkred]
              > > > and returns ScheduledJobs. The section of my code that performs the[/color][/color]
              > query[color=green][color=darkred]
              > > > is contained in a delegate function that I execute via a second[/color][/color][/color]
              thread.[color=blue]
              > On[color=green]
              > > 1[color=darkred]
              > > > or 2 of the 600+ servers the query hangs. I've tried to use[/color][/color]
              > Thread.Join()[color=green][color=darkred]
              > > > coupled with a Thread.Abort() but this does not kill the thread.
              > > >
              > > > Based on other post I've read this is a common occurrence and the only[/color][/color]
              > way[color=green][color=darkred]
              > > > to kill this thread is to use TerminateThread () located in the[/color]
              > > Kernel32.dll.[color=darkred]
              > > > I'm not really sure how to call this unmanaged code. Also[/color]
              > > TerminateThread ()[color=darkred]
              > > > requires the thread's handle and I'm not sure how to obtain this in[/color][/color]
              > .NET.[color=green][color=darkred]
              > > > I've made a "best guess" at the code but it doesn't work. See sample[/color]
              > > below.[color=darkred]
              > > > Can anyone give me a code sample of how this can be done? This is my[/color]
              > > first[color=darkred]
              > > > multi-threaded application and I'm pretty much a newbie to unmanaged[/color][/color]
              > code.[color=green]
              > >[color=darkred]
              > > >
              > > > // This class allows me to pass a server name to the function
              > > > // and still call it as a delegate.
              > > >
              > > > public class Parcer
              > > > {
              > > > public int ThreadID;
              > > > private string Server;
              > > > public DataSet ds;
              > > > public Parcer(string Server)
              > > > {
              > > > this.Server = Server;
              > > > }
              > > >
              > > > public void ParceJobs()
              > > > {
              > > > ThreadID = AppDomain.GetCu rrentThreadId() ;
              > > > IntelJobReader JobReader = new IntelJobReader( ); //Instanciate[/color][/color]
              > the[color=green][color=darkred]
              > > > JobReader object. This is a class I wrote that make the WMI calls and
              > > > returns a DataSet.
              > > > DataSet JobSchedules = ( DataSet ) ([/color]
              > > JobReader.GetSv rJobs(Server) );[color=darkred]
              > > > this.ds = JobSchedules;
              > > > }
              > > > }
              > > >
              > > > // This is my best guess at the unmanaged code. It runs without error[/color][/color]
              > but[color=green][color=darkred]
              > > > does not terminate the thread.
              > > >
              > > > public class Win32
              > > > {
              > > > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
              > > > public static extern int TerminateThread (int hThread);
              > > > }
              > > >
              > > > // Excerpt from my Conseole App's Main code:
              > > >
              > > > Parcer SchJobs = new Parcer(Server);
              > > > Thread JobTimeout = new Thread(new ThreadStart(Sch Jobs.ParceJobs) );
              > > > JobTimeout.Star t();
              > > > JobTimeout.Join (10000);
              > > > if (!JobTimeout.Jo in(10000))
              > > > {
              > > > JobTimeout.Abor t(); // This will not terminate the thread
              > > > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
              > > > Console.WriteLi ne("The thread timed out no change will be made to[/color][/color]
              > the[color=green][color=darkred]
              > > > DB");
              > > > }
              > > >
              > > > Thanks,
              > > > Bryan
              > > >
              > > >[/color]
              > >
              > >[/color]
              >[/color]


              Comment

              • Willy Denoyette [MVP]

                #8
                Re: Calling Win32 TerminateThread () via unmanaged code

                Agreed, TerminateThread is a no no in managed land (IMO this API should
                never have been publicly exposed :-)).
                But OP doesn't call through P/Invoke, he's using the Management classes
                which do sit on top of COM WMI, things get even more complicated as OP is
                calling remote WMI services on 600+ remote PC's.
                Remoting WMI services are implemented over SMB RPC's, not DCOM, only the
                fact that some of the remote servers are unavailable or not responding, will
                disturb the whole process if not carefully designed.
                Another thing that complicates maters is the interfacing between .NET and
                COM, which imposes threading requirements usually not know by the average
                ..NET developer (.NET replaces COM right?).

                Willy.


                "Dave" <noSpamdlevineN NTP2@wi.rr.com> wrote in message
                news:e2V31f8uDH A.2712@tk2msftn gp13.phx.gbl...[color=blue]
                > Calling TerminateThread will not do what you want it to do. Even if you[/color]
                were[color=blue]
                > able to kill the underlying OS thread the CLR will not "know" that you did
                > this and so the CLR's managed thread would still be waiting (forever) for
                > the unmanaged thread to return back to the managed world.
                >
                > In addition, killing an OS thread has LOTS of side-effects; its stack[/color]
                never[color=blue]
                > gets deallocated, mutexes and critical sections it owns never get released
                > etc. Unless your own code controls the thread (setting up its own[/color]
                restricted[color=blue]
                > environment so that it cannot allocate a system resource that requires
                > cleanup) it is very dangerous to do this. Even in Win32 land the docs warn
                > you to only do this as an asbolute last resort. Based on your sample code
                > there's nothing there that appears to be of such a mission critical nature
                > that this is required.
                >
                > IMO this is one of the areas in .NET that is not completely baked. It's[/color]
                done[color=blue]
                > well enough that you want to do use it but there really isn't enough[/color]
                control[color=blue]
                > over the execution model that you can reliably control other threads. This
                > is especially noticable in the case you've run into, that of P/Invoking to
                > an unmanaged API that hangs.
                >
                > An option you can take all the code that p/invokes and may hang and remote
                > it from another appdomain. When you want to terminate all those threads
                > unload the appdomain. I've noticed that the runtime does a better job of
                > unwinding all those threads when it unloads an appdomain then when you
                > simply try to abort the thread. Make sure you mark all those threads as
                > background.
                >
                >
                > "Bryan" <techie77@veriz on.net> wrote in message
                > news:RscAb.1302 $%01.238@nwrddc 02.gnilink.net. ..[color=green]
                > > Thanks for the reply. I do call the Abort before the Join however the
                > > thread still hangs. Any idea how I can create the pointer to the thread[/color]
                > and[color=green]
                > > call TerminateThread ()?
                > >
                > >
                > >
                > > "Dmitriy Lapshin [C# / .NET MVP]" <x-code@no-spam-please.hotpop.c om>[/color][/color]
                wrote[color=blue][color=green]
                > > in message news:upmtIewuDH A.1744@TK2MSFTN GP12.phx.gbl...[color=darkred]
                > > > > On 1 or 2 of the 600+ servers the query hangs. I've tried to use
                > > > Thread.Join()
                > > > > coupled with a Thread.Abort() but this does not kill the thread.
                > > >
                > > > Ensure the sequence was Thread.Abort() first and then Thread.Join(),[/color][/color][/color]
                not[color=blue][color=green]
                > > the[color=darkred]
                > > > other way around.
                > > > Calling Thread.Join() first will result in a deadlock you are probably
                > > > experiencing.
                > > >
                > > > As for the TerminateThread , this API function has two parameters (the[/color]
                > > second[color=darkred]
                > > > one is also int), but I am not sure how one can obtain the handle of[/color][/color][/color]
                the[color=blue][color=green][color=darkred]
                > > > thread. You might need to resort to the GetCurrentThrea d() API to do[/color][/color]
                > that.[color=green][color=darkred]
                > > >
                > > > --
                > > > Dmitriy Lapshin [C# / .NET MVP]
                > > > X-Unity Test Studio
                > > > http://x-unity.miik.com.ua/teststudio.aspx
                > > > Bring the power of unit testing to VS .NET IDE
                > > >
                > > > "Bryan" <techie77@veriz on.net> wrote in message
                > > > news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...
                > > > > I have a multi-threaded C# console application that uses WMI
                > > > > (System.Managem ent namespace) to make RPC calls to several servers[/color]
                > > (600+ )[color=darkred]
                > > > > and returns ScheduledJobs. The section of my code that performs the[/color]
                > > query[color=darkred]
                > > > > is contained in a delegate function that I execute via a second[/color][/color]
                > thread.[color=green]
                > > On[color=darkred]
                > > > 1
                > > > > or 2 of the 600+ servers the query hangs. I've tried to use[/color]
                > > Thread.Join()[color=darkred]
                > > > > coupled with a Thread.Abort() but this does not kill the thread.
                > > > >
                > > > > Based on other post I've read this is a common occurrence and the[/color][/color][/color]
                only[color=blue][color=green]
                > > way[color=darkred]
                > > > > to kill this thread is to use TerminateThread () located in the
                > > > Kernel32.dll.
                > > > > I'm not really sure how to call this unmanaged code. Also
                > > > TerminateThread ()
                > > > > requires the thread's handle and I'm not sure how to obtain this in[/color]
                > > .NET.[color=darkred]
                > > > > I've made a "best guess" at the code but it doesn't work. See[/color][/color][/color]
                sample[color=blue][color=green][color=darkred]
                > > > below.
                > > > > Can anyone give me a code sample of how this can be done? This is[/color][/color][/color]
                my[color=blue][color=green][color=darkred]
                > > > first
                > > > > multi-threaded application and I'm pretty much a newbie to unmanaged[/color]
                > > code.[color=darkred]
                > > > >
                > > > > // This class allows me to pass a server name to the function
                > > > > // and still call it as a delegate.
                > > > >
                > > > > public class Parcer
                > > > > {
                > > > > public int ThreadID;
                > > > > private string Server;
                > > > > public DataSet ds;
                > > > > public Parcer(string Server)
                > > > > {
                > > > > this.Server = Server;
                > > > > }
                > > > >
                > > > > public void ParceJobs()
                > > > > {
                > > > > ThreadID = AppDomain.GetCu rrentThreadId() ;
                > > > > IntelJobReader JobReader = new IntelJobReader( );[/color][/color][/color]
                //Instanciate[color=blue][color=green]
                > > the[color=darkred]
                > > > > JobReader object. This is a class I wrote that make the WMI calls[/color][/color][/color]
                and[color=blue][color=green][color=darkred]
                > > > > returns a DataSet.
                > > > > DataSet JobSchedules = ( DataSet ) (
                > > > JobReader.GetSv rJobs(Server) );
                > > > > this.ds = JobSchedules;
                > > > > }
                > > > > }
                > > > >
                > > > > // This is my best guess at the unmanaged code. It runs without[/color][/color][/color]
                error[color=blue][color=green]
                > > but[color=darkred]
                > > > > does not terminate the thread.
                > > > >
                > > > > public class Win32
                > > > > {
                > > > > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
                > > > > public static extern int TerminateThread (int hThread);
                > > > > }
                > > > >
                > > > > // Excerpt from my Conseole App's Main code:
                > > > >
                > > > > Parcer SchJobs = new Parcer(Server);
                > > > > Thread JobTimeout = new Thread(new ThreadStart(Sch Jobs.ParceJobs) );
                > > > > JobTimeout.Star t();
                > > > > JobTimeout.Join (10000);
                > > > > if (!JobTimeout.Jo in(10000))
                > > > > {
                > > > > JobTimeout.Abor t(); // This will not terminate the thread
                > > > > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
                > > > > Console.WriteLi ne("The thread timed out no change will be made[/color][/color][/color]
                to[color=blue][color=green]
                > > the[color=darkred]
                > > > > DB");
                > > > > }
                > > > >
                > > > > Thanks,
                > > > > Bryan
                > > > >
                > > > >
                > > >[/color]
                > >
                > >[/color]
                >
                >[/color]


                Comment

                • Bryan

                  #9
                  Re: Calling Win32 TerminateThread () via unmanaged code

                  Thanks for your help guys what you are saying makes sense. Since the call
                  is unmanaged even if the thread is "terminated".NE T won't know it. I've
                  seen this problem posted a few times on various news groups and have never
                  seen an actual Microsoft response. It seems to me that this is an issue
                  that really needs to be addressed.

                  I've never tried to initiate a separate AppDomain but I'm sure I can figure
                  it out. I'll do some research and give it a try. Will post a solution when
                  I have one.


                  Thanks again,
                  Bryan


                  "Willy Denoyette [MVP]" <willy.denoyett e@pandora.be> wrote in message
                  news:%23xbkIECv DHA.3140@TK2MSF TNGP11.phx.gbl. ..[color=blue]
                  > Agreed, TerminateThread is a no no in managed land (IMO this API should
                  > never have been publicly exposed :-)).
                  > But OP doesn't call through P/Invoke, he's using the Management classes
                  > which do sit on top of COM WMI, things get even more complicated as OP is
                  > calling remote WMI services on 600+ remote PC's.
                  > Remoting WMI services are implemented over SMB RPC's, not DCOM, only the
                  > fact that some of the remote servers are unavailable or not responding,[/color]
                  will[color=blue]
                  > disturb the whole process if not carefully designed.
                  > Another thing that complicates maters is the interfacing between .NET and
                  > COM, which imposes threading requirements usually not know by the average
                  > .NET developer (.NET replaces COM right?).
                  >
                  > Willy.
                  >
                  >
                  > "Dave" <noSpamdlevineN NTP2@wi.rr.com> wrote in message
                  > news:e2V31f8uDH A.2712@tk2msftn gp13.phx.gbl...[color=green]
                  > > Calling TerminateThread will not do what you want it to do. Even if you[/color]
                  > were[color=green]
                  > > able to kill the underlying OS thread the CLR will not "know" that you[/color][/color]
                  did[color=blue][color=green]
                  > > this and so the CLR's managed thread would still be waiting (forever)[/color][/color]
                  for[color=blue][color=green]
                  > > the unmanaged thread to return back to the managed world.
                  > >
                  > > In addition, killing an OS thread has LOTS of side-effects; its stack[/color]
                  > never[color=green]
                  > > gets deallocated, mutexes and critical sections it owns never get[/color][/color]
                  released[color=blue][color=green]
                  > > etc. Unless your own code controls the thread (setting up its own[/color]
                  > restricted[color=green]
                  > > environment so that it cannot allocate a system resource that requires
                  > > cleanup) it is very dangerous to do this. Even in Win32 land the docs[/color][/color]
                  warn[color=blue][color=green]
                  > > you to only do this as an asbolute last resort. Based on your sample[/color][/color]
                  code[color=blue][color=green]
                  > > there's nothing there that appears to be of such a mission critical[/color][/color]
                  nature[color=blue][color=green]
                  > > that this is required.
                  > >
                  > > IMO this is one of the areas in .NET that is not completely baked. It's[/color]
                  > done[color=green]
                  > > well enough that you want to do use it but there really isn't enough[/color]
                  > control[color=green]
                  > > over the execution model that you can reliably control other threads.[/color][/color]
                  This[color=blue][color=green]
                  > > is especially noticable in the case you've run into, that of P/Invoking[/color][/color]
                  to[color=blue][color=green]
                  > > an unmanaged API that hangs.
                  > >
                  > > An option you can take all the code that p/invokes and may hang and[/color][/color]
                  remote[color=blue][color=green]
                  > > it from another appdomain. When you want to terminate all those threads
                  > > unload the appdomain. I've noticed that the runtime does a better job of
                  > > unwinding all those threads when it unloads an appdomain then when you
                  > > simply try to abort the thread. Make sure you mark all those threads as
                  > > background.
                  > >
                  > >
                  > > "Bryan" <techie77@veriz on.net> wrote in message
                  > > news:RscAb.1302 $%01.238@nwrddc 02.gnilink.net. ..[color=darkred]
                  > > > Thanks for the reply. I do call the Abort before the Join however the
                  > > > thread still hangs. Any idea how I can create the pointer to the[/color][/color][/color]
                  thread[color=blue][color=green]
                  > > and[color=darkred]
                  > > > call TerminateThread ()?
                  > > >
                  > > >
                  > > >
                  > > > "Dmitriy Lapshin [C# / .NET MVP]" <x-code@no-spam-please.hotpop.c om>[/color][/color]
                  > wrote[color=green][color=darkred]
                  > > > in message news:upmtIewuDH A.1744@TK2MSFTN GP12.phx.gbl...
                  > > > > > On 1 or 2 of the 600+ servers the query hangs. I've tried to use
                  > > > > Thread.Join()
                  > > > > > coupled with a Thread.Abort() but this does not kill the thread.
                  > > > >
                  > > > > Ensure the sequence was Thread.Abort() first and then Thread.Join(),[/color][/color]
                  > not[color=green][color=darkred]
                  > > > the
                  > > > > other way around.
                  > > > > Calling Thread.Join() first will result in a deadlock you are[/color][/color][/color]
                  probably[color=blue][color=green][color=darkred]
                  > > > > experiencing.
                  > > > >
                  > > > > As for the TerminateThread , this API function has two parameters[/color][/color][/color]
                  (the[color=blue][color=green][color=darkred]
                  > > > second
                  > > > > one is also int), but I am not sure how one can obtain the handle of[/color][/color]
                  > the[color=green][color=darkred]
                  > > > > thread. You might need to resort to the GetCurrentThrea d() API to do[/color]
                  > > that.[color=darkred]
                  > > > >
                  > > > > --
                  > > > > Dmitriy Lapshin [C# / .NET MVP]
                  > > > > X-Unity Test Studio
                  > > > > http://x-unity.miik.com.ua/teststudio.aspx
                  > > > > Bring the power of unit testing to VS .NET IDE
                  > > > >
                  > > > > "Bryan" <techie77@veriz on.net> wrote in message
                  > > > > news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...
                  > > > > > I have a multi-threaded C# console application that uses WMI
                  > > > > > (System.Managem ent namespace) to make RPC calls to several servers
                  > > > (600+ )
                  > > > > > and returns ScheduledJobs. The section of my code that performs[/color][/color][/color]
                  the[color=blue][color=green][color=darkred]
                  > > > query
                  > > > > > is contained in a delegate function that I execute via a second[/color]
                  > > thread.[color=darkred]
                  > > > On
                  > > > > 1
                  > > > > > or 2 of the 600+ servers the query hangs. I've tried to use
                  > > > Thread.Join()
                  > > > > > coupled with a Thread.Abort() but this does not kill the thread.
                  > > > > >
                  > > > > > Based on other post I've read this is a common occurrence and the[/color][/color]
                  > only[color=green][color=darkred]
                  > > > way
                  > > > > > to kill this thread is to use TerminateThread () located in the
                  > > > > Kernel32.dll.
                  > > > > > I'm not really sure how to call this unmanaged code. Also
                  > > > > TerminateThread ()
                  > > > > > requires the thread's handle and I'm not sure how to obtain this[/color][/color][/color]
                  in[color=blue][color=green][color=darkred]
                  > > > .NET.
                  > > > > > I've made a "best guess" at the code but it doesn't work. See[/color][/color]
                  > sample[color=green][color=darkred]
                  > > > > below.
                  > > > > > Can anyone give me a code sample of how this can be done? This is[/color][/color]
                  > my[color=green][color=darkred]
                  > > > > first
                  > > > > > multi-threaded application and I'm pretty much a newbie to[/color][/color][/color]
                  unmanaged[color=blue][color=green][color=darkred]
                  > > > code.
                  > > > > >
                  > > > > > // This class allows me to pass a server name to the function
                  > > > > > // and still call it as a delegate.
                  > > > > >
                  > > > > > public class Parcer
                  > > > > > {
                  > > > > > public int ThreadID;
                  > > > > > private string Server;
                  > > > > > public DataSet ds;
                  > > > > > public Parcer(string Server)
                  > > > > > {
                  > > > > > this.Server = Server;
                  > > > > > }
                  > > > > >
                  > > > > > public void ParceJobs()
                  > > > > > {
                  > > > > > ThreadID = AppDomain.GetCu rrentThreadId() ;
                  > > > > > IntelJobReader JobReader = new IntelJobReader( );[/color][/color]
                  > //Instanciate[color=green][color=darkred]
                  > > > the
                  > > > > > JobReader object. This is a class I wrote that make the WMI calls[/color][/color]
                  > and[color=green][color=darkred]
                  > > > > > returns a DataSet.
                  > > > > > DataSet JobSchedules = ( DataSet ) (
                  > > > > JobReader.GetSv rJobs(Server) );
                  > > > > > this.ds = JobSchedules;
                  > > > > > }
                  > > > > > }
                  > > > > >
                  > > > > > // This is my best guess at the unmanaged code. It runs without[/color][/color]
                  > error[color=green][color=darkred]
                  > > > but
                  > > > > > does not terminate the thread.
                  > > > > >
                  > > > > > public class Win32
                  > > > > > {
                  > > > > > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
                  > > > > > public static extern int TerminateThread (int hThread);
                  > > > > > }
                  > > > > >
                  > > > > > // Excerpt from my Conseole App's Main code:
                  > > > > >
                  > > > > > Parcer SchJobs = new Parcer(Server);
                  > > > > > Thread JobTimeout = new Thread(new[/color][/color][/color]
                  ThreadStart(Sch Jobs.ParceJobs) );[color=blue][color=green][color=darkred]
                  > > > > > JobTimeout.Star t();
                  > > > > > JobTimeout.Join (10000);
                  > > > > > if (!JobTimeout.Jo in(10000))
                  > > > > > {
                  > > > > > JobTimeout.Abor t(); // This will not terminate the thread
                  > > > > > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
                  > > > > > Console.WriteLi ne("The thread timed out no change will be made[/color][/color]
                  > to[color=green][color=darkred]
                  > > > the
                  > > > > > DB");
                  > > > > > }
                  > > > > >
                  > > > > > Thanks,
                  > > > > > Bryan
                  > > > > >
                  > > > > >
                  > > > >
                  > > >
                  > > >[/color]
                  > >
                  > >[/color]
                  >
                  >[/color]


                  Comment

                  • Dave

                    #10
                    Re: Calling Win32 TerminateThread () via unmanaged code


                    "Willy Denoyette [MVP]" <willy.denoyett e@pandora.be> wrote in message
                    news:%23xbkIECv DHA.3140@TK2MSF TNGP11.phx.gbl. ..
                    [color=blue]
                    > Agreed, TerminateThread is a no no in managed land (IMO this API should
                    > never have been publicly exposed :-)).[/color]

                    Actually I disagree. It's usually abused and used incorrectly but for some
                    applications there is no substitute. We only used it as an absolute last
                    resort but it was necessary (and we did understand all the downsides to it).


                    IMO .NET wont be a suitable replacement for some Win32 apps until it has a
                    better story on a few key issues; aborting threads blocked in unmanaged
                    code, and uninterruptable finally blocks.
                    [color=blue]
                    > But OP doesn't call through P/Invoke, he's using the Management classes
                    > which do sit on top of COM WMI, things get even more complicated as OP is[/color]

                    I must be acronym challenged this morning; what does OP stand for?
                    [color=blue]
                    > calling remote WMI services on 600+ remote PC's.
                    > Remoting WMI services are implemented over SMB RPC's, not DCOM, only the>[/color]
                    fact that some of the remote servers are unavailable or not responding, will[color=blue]
                    > disturb the whole process if not carefully designed.
                    > Another thing that complicates maters is the interfacing between .NET and
                    > COM, which imposes threading requirements usually not know by the average
                    > .NET developer (.NET replaces COM right?).
                    >[/color]

                    I don't understand those issues that well - I skipped over most of the COM
                    era and went from Win32 to .NET. What sorts of threading related issues can
                    you point out that I (everyone) should be aware of?


                    Comment

                    • Dmitriy Lapshin [C# / .NET MVP]

                      #11
                      Re: Calling Win32 TerminateThread () via unmanaged code

                      Willy,

                      I was asking this because I am facing a similar problem. There's a managed
                      thread that does some work and should be able to be terminated at any time
                      by the user clicking on a kind of "Stop" button (like in IE). The thread to
                      be stopped is expected to mainly execute managed code, but it is not
                      guaranteed it will never use P/Invoke (the main part of the thread's
                      activity is running a third-party code I can make no assumptions of). In
                      this scenario, I believe there is no other way to stop the thread than
                      calling TerminateThread - of course when Thread.Abort() and Thread.Join
                      timed out.

                      --
                      Dmitriy Lapshin [C# / .NET MVP]
                      X-Unity Test Studio

                      Bring the power of unit testing to VS .NET IDE

                      "Willy Denoyette [MVP]" <willy.denoyett e@pandora.be> wrote in message
                      news:u15zE7BvDH A.2072@TK2MSFTN GP10.phx.gbl...[color=blue]
                      > It doesn't relate, my point was to forget about aborting a thread
                      > asynchronously.
                      > IMO, OP should take a look at the WMI related code, maybe WMI calls could[/color]
                      be[color=blue]
                      > done asynchronously i.s.o synchronously (blocking), that way you don't[/color]
                      have[color=blue]
                      > to try to abort a blocked thread (something that doesn't work after all,
                      > unless by calling ThreadTerminate ).
                      >
                      > Willy.
                      >
                      >
                      > "Dmitriy Lapshin [C# / .NET MVP]" <x-code@no-spam-please.hotpop.c om> wrote
                      > in message news:uFkPD4yuDH A.2224@TK2MSFTN GP10.phx.gbl...[color=green]
                      > > Hello Willy,
                      > >[color=darkred]
                      > > > Another point to check is whether your code runs on a MTA thread (see
                      > > > MTA/STAThread attribute on Main), too many people get bitten by this.[/color]
                      > >
                      > > Could you please elaborate on this? I know what is STA and what is MTA,[/color]
                      > but[color=green]
                      > > how does it related to aborting a worker thread?
                      > >
                      > > --
                      > > Dmitriy Lapshin [C# / .NET MVP]
                      > > X-Unity Test Studio
                      > > http://x-unity.miik.com.ua/teststudio.aspx
                      > > Bring the power of unit testing to VS .NET IDE
                      > >
                      > > "Willy Denoyette [MVP]" <willy.denoyett e@pandora.be> wrote in message
                      > > news:OtV0jwxuDH A.2180@TK2MSFTN GP09.phx.gbl...[color=darkred]
                      > > > You should never call ThreadTerminate , it will corrupt the process, or
                      > > > worse, if called while it holds a lock on the OS heap, all other[/color][/color][/color]
                      threads[color=blue][color=green]
                      > > in[color=darkred]
                      > > > the system trying to allocate/free memory blocks from the same heap[/color][/color][/color]
                      will[color=blue][color=green][color=darkred]
                      > > > block forever.
                      > > > Calling Thread.Abort() from another thread (asynch.) is also[/color][/color]
                      > problematic:[color=green][color=darkred]
                      > > > 1. When the thread is blocked in unmanaged code, Abort will suspend[/color][/color]
                      > until[color=green]
                      > > a[color=darkred]
                      > > > return from unmanaged code is done and a safe point for GC is reached.
                      > > > 2. Asynchronous Thread.Abort's should be deferred when executing a[/color][/color]
                      > finally[color=green][color=darkred]
                      > > > clause, this is not done in v1.1, possibly resulting in resource leaks[/color][/color]
                      > and[color=green][color=darkred]
                      > > > corrupted state.
                      > > >
                      > > > I would suggest you revise the portion of your "Management/WMI" code,[/color][/color]
                      > IMO[color=green][color=darkred]
                      > > > the solution should be found in there as it's the source of the[/color][/color][/color]
                      problem[color=blue][color=green][color=darkred]
                      > > > (blocking thread).
                      > > > Another point to check is whether your code runs on a MTA thread (see
                      > > > MTA/STAThread attribute on Main), too many people get bitten by this.
                      > > >
                      > > > Willy.
                      > > >
                      > > >
                      > > > "Bryan" <techie77@veriz on.net> wrote in message
                      > > > news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...
                      > > > > I have a multi-threaded C# console application that uses WMI
                      > > > > (System.Managem ent namespace) to make RPC calls to several servers[/color]
                      > > (600+ )[color=darkred]
                      > > > > and returns ScheduledJobs. The section of my code that performs the[/color]
                      > > query[color=darkred]
                      > > > > is contained in a delegate function that I execute via a second[/color][/color]
                      > thread.[color=green]
                      > > On[color=darkred]
                      > > > 1
                      > > > > or 2 of the 600+ servers the query hangs. I've tried to use[/color]
                      > > Thread.Join()[color=darkred]
                      > > > > coupled with a Thread.Abort() but this does not kill the thread.
                      > > > >
                      > > > > Based on other post I've read this is a common occurrence and the[/color][/color][/color]
                      only[color=blue][color=green]
                      > > way[color=darkred]
                      > > > > to kill this thread is to use TerminateThread () located in the
                      > > > Kernel32.dll.
                      > > > > I'm not really sure how to call this unmanaged code. Also
                      > > > TerminateThread ()
                      > > > > requires the thread's handle and I'm not sure how to obtain this in[/color]
                      > > .NET.[color=darkred]
                      > > > > I've made a "best guess" at the code but it doesn't work. See[/color][/color][/color]
                      sample[color=blue][color=green][color=darkred]
                      > > > below.
                      > > > > Can anyone give me a code sample of how this can be done? This is[/color][/color][/color]
                      my[color=blue][color=green][color=darkred]
                      > > > first
                      > > > > multi-threaded application and I'm pretty much a newbie to unmanaged[/color]
                      > > code.[color=darkred]
                      > > >
                      > > > >
                      > > > > // This class allows me to pass a server name to the function
                      > > > > // and still call it as a delegate.
                      > > > >
                      > > > > public class Parcer
                      > > > > {
                      > > > > public int ThreadID;
                      > > > > private string Server;
                      > > > > public DataSet ds;
                      > > > > public Parcer(string Server)
                      > > > > {
                      > > > > this.Server = Server;
                      > > > > }
                      > > > >
                      > > > > public void ParceJobs()
                      > > > > {
                      > > > > ThreadID = AppDomain.GetCu rrentThreadId() ;
                      > > > > IntelJobReader JobReader = new IntelJobReader( );[/color][/color][/color]
                      //Instanciate[color=blue][color=green]
                      > > the[color=darkred]
                      > > > > JobReader object. This is a class I wrote that make the WMI calls[/color][/color][/color]
                      and[color=blue][color=green][color=darkred]
                      > > > > returns a DataSet.
                      > > > > DataSet JobSchedules = ( DataSet ) (
                      > > > JobReader.GetSv rJobs(Server) );
                      > > > > this.ds = JobSchedules;
                      > > > > }
                      > > > > }
                      > > > >
                      > > > > // This is my best guess at the unmanaged code. It runs without[/color][/color][/color]
                      error[color=blue][color=green]
                      > > but[color=darkred]
                      > > > > does not terminate the thread.
                      > > > >
                      > > > > public class Win32
                      > > > > {
                      > > > > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
                      > > > > public static extern int TerminateThread (int hThread);
                      > > > > }
                      > > > >
                      > > > > // Excerpt from my Conseole App's Main code:
                      > > > >
                      > > > > Parcer SchJobs = new Parcer(Server);
                      > > > > Thread JobTimeout = new Thread(new ThreadStart(Sch Jobs.ParceJobs) );
                      > > > > JobTimeout.Star t();
                      > > > > JobTimeout.Join (10000);
                      > > > > if (!JobTimeout.Jo in(10000))
                      > > > > {
                      > > > > JobTimeout.Abor t(); // This will not terminate the thread
                      > > > > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
                      > > > > Console.WriteLi ne("The thread timed out no change will be made[/color][/color][/color]
                      to[color=blue][color=green]
                      > > the[color=darkred]
                      > > > > DB");
                      > > > > }
                      > > > >
                      > > > > Thanks,
                      > > > > Bryan
                      > > > >
                      > > > >
                      > > >
                      > > >[/color]
                      > >[/color]
                      >
                      >[/color]

                      Comment

                      • Willy Denoyette [MVP]

                        #12
                        Re: Calling Win32 TerminateThread () via unmanaged code

                        Dave,

                        See inline ***


                        "Dave" <noSpamdlevineN NTP2@wi.rr.com> wrote in message
                        news:%23PEIyQXv DHA.2136@TK2MSF TNGP10.phx.gbl. ..[color=blue]
                        >
                        > "Willy Denoyette [MVP]" <willy.denoyett e@pandora.be> wrote in message
                        > news:%23xbkIECv DHA.3140@TK2MSF TNGP11.phx.gbl. ..
                        >[color=green]
                        > > Agreed, TerminateThread is a no no in managed land (IMO this API should
                        > > never have been publicly exposed :-)).[/color]
                        >
                        > Actually I disagree. It's usually abused and used incorrectly but for some
                        > applications there is no substitute. We only used it as an absolute last
                        > resort but it was necessary (and we did understand all the downsides to[/color]
                        it).

                        *** Even Microsoft call this a dangerous API (see
                        http://msdn.microsoft.com/library/de...atethread.asp),
                        and IMO it's a good thing there is no analog in the CLR.
                        In unmanaged world, if you know ALL the downsides, just go ahead no problem,
                        but what makes you so sure of that?.

                        When you call TerminateThread aside from the fact that the thread
                        terminates, you are guaranteed that:
                        - the process state is almost left in a corrupted state
                        - resources like, thread stack, TLS slots, per-thread data that libs are
                        keeping, synchronization primitives... are never released.
                        - DLL's loaded don't get their DllMain called.
                        - Locks held by the OS heap manager are not released
                        That seems like you are injecting a serious bug in your code whenever you
                        call ThreadTerminate , isn't that anough to say that you may as well kill the
                        process.

                        In managed code, things are getting a lot more complicated, as you correctly
                        stated in your previous reply, simply because you don't "control all of the
                        code that the target thread could possibly be running at the time of the
                        termination", you should never call ThreadAbort".

                        If the thread fails to exit when you signal it to using Thread.Abort() or
                        any other signal, it's probably :
                        - Waiting for IO rundown, hat is running code in kernel mode - or worse
                        running driver code; you can solve this by using async IO, using timeouts, e
                        tc... but terminating the thread while in this state can be very dangerous.
                        - It's busy working, the thread may never leave a locked/guarded block(s)
                        possibly causing deadlocks.
                        - The code contains a bug that prevents the thread to exit when signaled to
                        do so.

                        So, IMO when you think you need to call TerminateThread , you have a bug or a
                        design flaw in your code, in that case you better of to kill the process (or
                        unload the Application Domain) than to call TerminateThread .

                        [color=blue]
                        >
                        > IMO .NET wont be a suitable replacement for some Win32 apps until it has a
                        > better story on a few key issues; aborting threads blocked in unmanaged
                        > code, and uninterruptable finally blocks.
                        >[/color]
                        **** Uninterruptable finally blocks are addressed/solved in v 2.0.
                        [color=blue][color=green]
                        > > But OP doesn't call through P/Invoke, he's using the Management classes
                        > > which do sit on top of COM WMI, things get even more complicated as OP[/color][/color]
                        is[color=blue]
                        >
                        > I must be acronym challenged this morning; what does OP stand for?
                        >[/color]
                        *** Original Poster
                        [color=blue][color=green]
                        > > calling remote WMI services on 600+ remote PC's.
                        > > Remoting WMI services are implemented over SMB RPC's, not DCOM, only[/color][/color]
                        the>[color=blue]
                        > fact that some of the remote servers are unavailable or not responding,[/color]
                        will[color=blue][color=green]
                        > > disturb the whole process if not carefully designed.
                        > > Another thing that complicates maters is the interfacing between .NET[/color][/color]
                        and[color=blue][color=green]
                        > > COM, which imposes threading requirements usually not know by the[/color][/color]
                        average[color=blue][color=green]
                        > > .NET developer (.NET replaces COM right?).
                        > >[/color]
                        >
                        > I don't understand those issues that well - I skipped over most of the COM
                        > era and went from Win32 to .NET. What sorts of threading related issues[/color]
                        can[color=blue]
                        > you point out that I (everyone) should be aware of?
                        >[/color]
                        *** A lot of system services offered by the FCL are simply wrappers around
                        existing system services build/implemented in native code accessed through
                        COM interop, I know a number of these will be replaced by managed code
                        system services (like Indigo in Longhorn) in the (not so near) future. Now,
                        COM has always had his own threading issues like synchronization and inter
                        thread marshalling and message passing , great deal of these
                        issues/complexities are nicely handled by COM/COM+ itself (see apartments,
                        message pumps, access/activation control, security etc..) another part is
                        covered by the development tools, f.i VB5/6 only makes it possible to
                        produce single threaded apartment components, but most (if not all) of the
                        system COM services are or free threaded, or support both single and
                        mutithreaded environments.
                        The CLR has no notion of COM and has no concept of apartments for their
                        run-time context, this is still handled by COM which is per default loaded
                        by the hosting process (even before the CLR is loaded) . In .NET, most of
                        these COM complexities are hidden from you (the developer), by the FCL and
                        the CLR, you shouldn't even know that COM is used, it's nothing more than
                        an implementation detail. But the complexities still exist, and the CLR
                        can't handle all of them, so sometimes it's good to know what the
                        requirements are and possibly help the CLR a bit before we get bitten by
                        some nasty bugs.

                        Willy.





                        Comment

                        • Willy Denoyette [MVP]

                          #13
                          Re: Calling Win32 TerminateThread () via unmanaged code

                          Dmitriy,
                          If the unmanaged code blocks (never returns), I would consider it as a bug
                          or at least a design flaws, calling TerminateThread wont solve these.
                          So if you regularery call TerminateThread , rest assured the process will be
                          left in a corrupted state and will die sooner or later.
                          You should only call "TerminateThrea d" if you control all of the code that
                          the target thread could possibly be running at the time of the termination,
                          in your example it's not the case so don't do it, terminating the process
                          (or unloading the AppDomain) is your only valid (but unfortunate)
                          alternative.

                          Willy.


                          "Dmitriy Lapshin [C# / .NET MVP]" <x-code@no-spam-please.hotpop.c om> wrote
                          in message news:eV3fRiYvDH A.1576@TK2MSFTN GP11.phx.gbl...[color=blue]
                          > Willy,
                          >
                          > I was asking this because I am facing a similar problem. There's a managed
                          > thread that does some work and should be able to be terminated at any time
                          > by the user clicking on a kind of "Stop" button (like in IE). The thread[/color]
                          to[color=blue]
                          > be stopped is expected to mainly execute managed code, but it is not
                          > guaranteed it will never use P/Invoke (the main part of the thread's
                          > activity is running a third-party code I can make no assumptions of). In
                          > this scenario, I believe there is no other way to stop the thread than
                          > calling TerminateThread - of course when Thread.Abort() and Thread.Join
                          > timed out.
                          >
                          > --
                          > Dmitriy Lapshin [C# / .NET MVP]
                          > X-Unity Test Studio
                          > http://x-unity.miik.com.ua/teststudio.aspx
                          > Bring the power of unit testing to VS .NET IDE
                          >
                          > "Willy Denoyette [MVP]" <willy.denoyett e@pandora.be> wrote in message
                          > news:u15zE7BvDH A.2072@TK2MSFTN GP10.phx.gbl...[color=green]
                          > > It doesn't relate, my point was to forget about aborting a thread
                          > > asynchronously.
                          > > IMO, OP should take a look at the WMI related code, maybe WMI calls[/color][/color]
                          could[color=blue]
                          > be[color=green]
                          > > done asynchronously i.s.o synchronously (blocking), that way you don't[/color]
                          > have[color=green]
                          > > to try to abort a blocked thread (something that doesn't work after all,
                          > > unless by calling ThreadTerminate ).
                          > >
                          > > Willy.
                          > >
                          > >
                          > > "Dmitriy Lapshin [C# / .NET MVP]" <x-code@no-spam-please.hotpop.c om>[/color][/color]
                          wrote[color=blue][color=green]
                          > > in message news:uFkPD4yuDH A.2224@TK2MSFTN GP10.phx.gbl...[color=darkred]
                          > > > Hello Willy,
                          > > >
                          > > > > Another point to check is whether your code runs on a MTA thread[/color][/color][/color]
                          (see[color=blue][color=green][color=darkred]
                          > > > > MTA/STAThread attribute on Main), too many people get bitten by[/color][/color][/color]
                          this.[color=blue][color=green][color=darkred]
                          > > >
                          > > > Could you please elaborate on this? I know what is STA and what is[/color][/color][/color]
                          MTA,[color=blue][color=green]
                          > > but[color=darkred]
                          > > > how does it related to aborting a worker thread?
                          > > >
                          > > > --
                          > > > Dmitriy Lapshin [C# / .NET MVP]
                          > > > X-Unity Test Studio
                          > > > http://x-unity.miik.com.ua/teststudio.aspx
                          > > > Bring the power of unit testing to VS .NET IDE
                          > > >
                          > > > "Willy Denoyette [MVP]" <willy.denoyett e@pandora.be> wrote in message
                          > > > news:OtV0jwxuDH A.2180@TK2MSFTN GP09.phx.gbl...
                          > > > > You should never call ThreadTerminate , it will corrupt the process,[/color][/color][/color]
                          or[color=blue][color=green][color=darkred]
                          > > > > worse, if called while it holds a lock on the OS heap, all other[/color][/color]
                          > threads[color=green][color=darkred]
                          > > > in
                          > > > > the system trying to allocate/free memory blocks from the same heap[/color][/color]
                          > will[color=green][color=darkred]
                          > > > > block forever.
                          > > > > Calling Thread.Abort() from another thread (asynch.) is also[/color]
                          > > problematic:[color=darkred]
                          > > > > 1. When the thread is blocked in unmanaged code, Abort will suspend[/color]
                          > > until[color=darkred]
                          > > > a
                          > > > > return from unmanaged code is done and a safe point for GC is[/color][/color][/color]
                          reached.[color=blue][color=green][color=darkred]
                          > > > > 2. Asynchronous Thread.Abort's should be deferred when executing a[/color]
                          > > finally[color=darkred]
                          > > > > clause, this is not done in v1.1, possibly resulting in resource[/color][/color][/color]
                          leaks[color=blue][color=green]
                          > > and[color=darkred]
                          > > > > corrupted state.
                          > > > >
                          > > > > I would suggest you revise the portion of your "Management/WMI"[/color][/color][/color]
                          code,[color=blue][color=green]
                          > > IMO[color=darkred]
                          > > > > the solution should be found in there as it's the source of the[/color][/color]
                          > problem[color=green][color=darkred]
                          > > > > (blocking thread).
                          > > > > Another point to check is whether your code runs on a MTA thread[/color][/color][/color]
                          (see[color=blue][color=green][color=darkred]
                          > > > > MTA/STAThread attribute on Main), too many people get bitten by[/color][/color][/color]
                          this.[color=blue][color=green][color=darkred]
                          > > > >
                          > > > > Willy.
                          > > > >
                          > > > >
                          > > > > "Bryan" <techie77@veriz on.net> wrote in message
                          > > > > news:yMTzb.5497 $lv4.3710@nwrdd c01.gnilink.net ...
                          > > > > > I have a multi-threaded C# console application that uses WMI
                          > > > > > (System.Managem ent namespace) to make RPC calls to several servers
                          > > > (600+ )
                          > > > > > and returns ScheduledJobs. The section of my code that performs[/color][/color][/color]
                          the[color=blue][color=green][color=darkred]
                          > > > query
                          > > > > > is contained in a delegate function that I execute via a second[/color]
                          > > thread.[color=darkred]
                          > > > On
                          > > > > 1
                          > > > > > or 2 of the 600+ servers the query hangs. I've tried to use
                          > > > Thread.Join()
                          > > > > > coupled with a Thread.Abort() but this does not kill the thread.
                          > > > > >
                          > > > > > Based on other post I've read this is a common occurrence and the[/color][/color]
                          > only[color=green][color=darkred]
                          > > > way
                          > > > > > to kill this thread is to use TerminateThread () located in the
                          > > > > Kernel32.dll.
                          > > > > > I'm not really sure how to call this unmanaged code. Also
                          > > > > TerminateThread ()
                          > > > > > requires the thread's handle and I'm not sure how to obtain this[/color][/color][/color]
                          in[color=blue][color=green][color=darkred]
                          > > > .NET.
                          > > > > > I've made a "best guess" at the code but it doesn't work. See[/color][/color]
                          > sample[color=green][color=darkred]
                          > > > > below.
                          > > > > > Can anyone give me a code sample of how this can be done? This is[/color][/color]
                          > my[color=green][color=darkred]
                          > > > > first
                          > > > > > multi-threaded application and I'm pretty much a newbie to[/color][/color][/color]
                          unmanaged[color=blue][color=green][color=darkred]
                          > > > code.
                          > > > >
                          > > > > >
                          > > > > > // This class allows me to pass a server name to the function
                          > > > > > // and still call it as a delegate.
                          > > > > >
                          > > > > > public class Parcer
                          > > > > > {
                          > > > > > public int ThreadID;
                          > > > > > private string Server;
                          > > > > > public DataSet ds;
                          > > > > > public Parcer(string Server)
                          > > > > > {
                          > > > > > this.Server = Server;
                          > > > > > }
                          > > > > >
                          > > > > > public void ParceJobs()
                          > > > > > {
                          > > > > > ThreadID = AppDomain.GetCu rrentThreadId() ;
                          > > > > > IntelJobReader JobReader = new IntelJobReader( );[/color][/color]
                          > //Instanciate[color=green][color=darkred]
                          > > > the
                          > > > > > JobReader object. This is a class I wrote that make the WMI calls[/color][/color]
                          > and[color=green][color=darkred]
                          > > > > > returns a DataSet.
                          > > > > > DataSet JobSchedules = ( DataSet ) (
                          > > > > JobReader.GetSv rJobs(Server) );
                          > > > > > this.ds = JobSchedules;
                          > > > > > }
                          > > > > > }
                          > > > > >
                          > > > > > // This is my best guess at the unmanaged code. It runs without[/color][/color]
                          > error[color=green][color=darkred]
                          > > > but
                          > > > > > does not terminate the thread.
                          > > > > >
                          > > > > > public class Win32
                          > > > > > {
                          > > > > > [DllImport("Kern el32.dll", CharSet=CharSet .Auto)]
                          > > > > > public static extern int TerminateThread (int hThread);
                          > > > > > }
                          > > > > >
                          > > > > > // Excerpt from my Conseole App's Main code:
                          > > > > >
                          > > > > > Parcer SchJobs = new Parcer(Server);
                          > > > > > Thread JobTimeout = new Thread(new[/color][/color][/color]
                          ThreadStart(Sch Jobs.ParceJobs) );[color=blue][color=green][color=darkred]
                          > > > > > JobTimeout.Star t();
                          > > > > > JobTimeout.Join (10000);
                          > > > > > if (!JobTimeout.Jo in(10000))
                          > > > > > {
                          > > > > > JobTimeout.Abor t(); // This will not terminate the thread
                          > > > > > Win32.Terminate Thread(AppDomai n.GetCurrentThr eadId());
                          > > > > > Console.WriteLi ne("The thread timed out no change will be made[/color][/color]
                          > to[color=green][color=darkred]
                          > > > the
                          > > > > > DB");
                          > > > > > }
                          > > > > >
                          > > > > > Thanks,
                          > > > > > Bryan
                          > > > > >
                          > > > > >
                          > > > >
                          > > > >
                          > > >[/color]
                          > >
                          > >[/color]
                          >[/color]


                          Comment

                          • Dave

                            #14
                            Re: Calling Win32 TerminateThread () via unmanaged code


                            See inline
                            [color=blue][color=green]
                            > >[/color]
                            > *** Even Microsoft call this a dangerous API (see
                            >[/color]
                            http://msdn.microsoft.com/library/de...atethread.asp),[color=blue]
                            > and IMO it's a good thing there is no analog in the CLR.
                            > In unmanaged world, if you know ALL the downsides, just go ahead no[/color]
                            problem,[color=blue]
                            > but what makes you so sure of that?.
                            >
                            > When you call TerminateThread aside from the fact that the thread
                            > terminates, you are guaranteed that:
                            > - the process state is almost left in a corrupted state
                            > - resources like, thread stack, TLS slots, per-thread data that libs are
                            > keeping, synchronization primitives... are never released.
                            > - DLL's loaded don't get their DllMain called.
                            > - Locks held by the OS heap manager are not released
                            > That seems like you are injecting a serious bug in your code whenever you
                            > call ThreadTerminate , isn't that anough to say that you may as well kill[/color]
                            the[color=blue]
                            > process.
                            >[/color]

                            Yes, we were aware of all that (and more). Most of the threads that we
                            executed were written in a custom language (which we defined), and compiled
                            by a custom compiler (ours). User threads were prevented from acquiring any
                            of those resources you mentioned - the language was very constrained. Most
                            threads were completely within our control, and we injected lots of control
                            points into the execution stream so that when we wanted to terminate a
                            thread we could get it to a known safe point before we shut it down using
                            other techniques to make it block. However, there was also the possibility
                            that when the execution controller determined that a watchdog limit was
                            exceeded and the thread should be stopped, that for whatever reason a thread
                            would not reach that known safe point. Since this was controlling real-world
                            processes we simply had to make a choice, and the downside of allowing an
                            uncontrollable thread to continue to run was too great a risk. We jumped
                            through lots of hoops to try to coax it into returning to being
                            well-behaved, but in the end (the absolute very end) we terminated it.

                            We usually only had problems when we called into a DLL that was written by
                            an outside party. If we ran into a problem like this with our own code we
                            treated it as a serious bug that required an instant bugfix. In actual
                            practice this was very rare (we usually had to contrive it), and I never did
                            come across a situation that resulted in the type of system corruption that
                            would require us to reboot. We also had lots of code to detect internal
                            corruption and to shut ourselves down in that event. We also had our own
                            internal debate along the same lines that you've put forth. It was a very
                            controversial subject.

                            I agree that it's just as well there is no counterpart in the CLR. The CLR
                            isn't suitable for this type of control anyway (at least, not yet). If they
                            ever get a version of the CLR to run in the kernel then its time to expose a
                            TerminateThread API. Long before I'll look for a TerminateThread API I'd
                            rather see a thread control environment more amenable for control purposes
                            (f.e. more priority levels - 5 is a joke).

                            [color=blue]
                            > In managed code, things are getting a lot more complicated, as you[/color]
                            correctly[color=blue]
                            > stated in your previous reply, simply because you don't "control all of[/color]
                            the[color=blue]
                            > code that the target thread could possibly be running at the time of the
                            > termination", you should never call ThreadAbort".
                            >[/color]
                            Agreed. There are too many other means of signalling a thread, unless you
                            are just plain lazy.
                            [color=blue]
                            > If the thread fails to exit when you signal it to using Thread.Abort() or
                            > any other signal, it's probably :
                            > - Waiting for IO rundown, hat is running code in kernel mode - or worse
                            > running driver code; you can solve this by using async IO, using timeouts,[/color]

                            You can do this if you write the code yourself, but if all you have is an
                            API that doesn't expose an async mechanism you are at their mercy. There are
                            lots of APIs that do something like wait for user input before returning. If
                            that input never comes the API never returns ==> hang.
                            [color=blue]
                            > etc... but terminating the thread while in this state can be very[/color]
                            dangerous.- It's busy working, the thread may never leave a locked/guarded
                            block(s)[color=blue]
                            > possibly causing deadlocks.
                            > - The code contains a bug that prevents the thread to exit when signaled[/color]
                            to[color=blue]
                            > do so.
                            >
                            > So, IMO when you think you need to call TerminateThread , you have a bug or[/color]
                            a[color=blue]
                            > design flaw in your code, in that case you better of to kill the process[/color]
                            (or[color=blue]
                            > unload the Application Domain) than to call TerminateThread .
                            >[/color]

                            I think you misunderstand me. I am not advocating using TerminateThread
                            (especially from within .NET), exactly the opposite. As I stated earlier,
                            dumping the AppDomain usually works, and when it doesn't usually the other
                            recourse is to exit the app and correct the problem. I'd like to see the CLR
                            team work on this; it's the source of a lot of problems.

                            My only point was that in some cases, when you understand the issues and are
                            willing to deal with them, even dangerous APIs have their uses. And I'll end
                            this with the observation that this API has been in Win32 for over 10
                            years...if it was really such that it should never be called under any
                            circumstances then the Win32 group should have deprecated this API years
                            ago.

                            [color=blue]
                            >[color=green]
                            > >
                            > > IMO .NET wont be a suitable replacement for some Win32 apps until it has[/color][/color]
                            a[color=blue][color=green]
                            > > better story on a few key issues; aborting threads blocked in unmanaged
                            > > code, and uninterruptable finally blocks.
                            > >[/color]
                            > **** Uninterruptable finally blocks are addressed/solved in v 2.0.
                            >[/color]

                            THAT will be a big plus.


                            [color=blue]
                            > *** A lot of system services offered by the FCL are simply wrappers around
                            > existing system services build/implemented in native code accessed through
                            > COM interop, I know a number of these will be replaced by managed code
                            > system services (like Indigo in Longhorn) in the (not so near) future.[/color]
                            Now,[color=blue]
                            > COM has always had his own threading issues like synchronization and inter
                            > thread marshalling and message passing , great deal of these
                            > issues/complexities are nicely handled by COM/COM+ itself (see apartments,[/color]
                            [color=blue]
                            > message pumps, access/activation control, security etc..) another part is
                            > covered by the development tools, f.i VB5/6 only makes it possible to
                            > produce single threaded apartment components, but most (if not all) of the
                            > system COM services are or free threaded, or support both single and
                            > mutithreaded environments.
                            > The CLR has no notion of COM and has no concept of apartments for their
                            > run-time context, this is still handled by COM which is per default loaded
                            > by the hosting process (even before the CLR is loaded) . In .NET, most of
                            > these COM complexities are hidden from you (the developer), by the FCL and
                            > the CLR, you shouldn't even know that COM is used, it's nothing more than
                            > an implementation detail. But the complexities still exist, and the CLR
                            > can't handle all of them, so sometimes it's good to know what the
                            > requirements are and possibly help the CLR a bit before we get bitten by
                            > some nasty bugs.
                            >[/color]

                            I understand Win32 threading fairly well but I never had gotten my head
                            wrapped around apartments and the weird COM threading models. I like the
                            fact that .NET makes most of those hassles go away so that we are back to
                            plain old threading again. Now the biggest problem I run into is convincing
                            all those people with a vested interest in COM components that they should
                            give it up and move into .NET. There's still a lot of resistance to that.



                            Comment

                            • Willy Denoyette [MVP]

                              #15
                              Re: Calling Win32 TerminateThread () via unmanaged code

                              Dave,

                              Inline

                              "Dave" <noSpamdlevineN NTP2@wi.rr.com> wrote in message
                              news:uO2HXwfvDH A.2000@TK2MSFTN GP11.phx.gbl...[color=blue]
                              >[/color]
                              [color=blue]
                              > I think you misunderstand me. I am not advocating using TerminateThread
                              > (especially from within .NET), exactly the opposite. As I stated earlier,
                              > dumping the AppDomain usually works, and when it doesn't usually the other
                              > recourse is to exit the app and correct the problem. I'd like to see the[/color]
                              CLR[color=blue]
                              > team work on this; it's the source of a lot of problems.
                              >[/color]
                              No, I know you are not advocating using TerminateThread , and from reading
                              your (interesting) replies, I'm pretty confident you know exactly what you
                              are talking about.
                              [color=blue]
                              > My only point was that in some cases, when you understand the issues and[/color]
                              are[color=blue]
                              > willing to deal with them, even dangerous APIs have their uses. And I'll[/color]
                              end[color=blue]
                              > this with the observation that this API has been in Win32 for over 10
                              > years...if it was really such that it should never be called under any
                              > circumstances then the Win32 group should have deprecated this API years
                              > ago.
                              >[/color]
                              Sure they have their uses, but as you probably know, API's like
                              TerminateThread are only recently called "dangerous" , just because many of
                              us had the oportunity to discover the "dangers". Now, the TerminateThread
                              service is there and can't be removed from existing OS'ses, so it's
                              important to know there is no use of it in managed code, and you should only
                              consider it for very special cases like the one you pictured.


                              [color=blue]
                              > I understand Win32 threading fairly well but I never had gotten my head
                              > wrapped around apartments and the weird COM threading models. I like the
                              > fact that .NET makes most of those hassles go away so that we are back to
                              > plain old threading again. Now the biggest problem I run into is[/color]
                              convincing[color=blue]
                              > all those people with a vested interest in COM components that they should
                              > give it up and move into .NET. There's still a lot of resistance to that.[/color]

                              Getting rid of COM is something that will takes years (maybe decades), and
                              basically there is nothing wrong with it. I even like the idea of COM being
                              used as a system level component architecture for the years to come, but at
                              the application level, one should try to get rid of it, or at least design
                              your interfaces so you can easely get rid of the requirements imposed by COM
                              at a later stage without breaking your clienst code.


                              Willy.


                              Comment

                              Working...