Silverfrost Forums

Welcome to our forums

.NET ThreadStart Delegate

10 Jul 2007 5:22 #2041

I have been trying to convert a user application to FTN95 .NET, and am having a problem getting ThreadStart delegate coded properly. Following code works except the instantiation of the AppStart object.

! TDTM - .NET Test Program

! Namespace Name

  MODULE UserApp

    LIBRARY 'System.dll'
    LIBRARY 'System.Data.dll'
    LIBRARY 'System.Drawing.dll'
    LIBRARY 'System.Windows.Forms.dll'
    LIBRARY 'SciPlot.dll'

    ASSEMBLY_EXTERNAL(name='System.Console.ReadLine') ReadLine
    ASSEMBLY_EXTERNAL(name='SciPlot.SP.EVTAPP')       EVTAPP
    ASSEMBLY_EXTERNAL(name='SciPlot.SPIde.IDEBEG')    IDEBEG
    ASSEMBLY_EXTERNAL(name='SciPlot.SPIde.IDERTN')    IDERTN

! Class Fields

    INTEGER(4):: IdeFlag

  END MODULE UserApp
                                                                  

! User Application:

  SUBROUTINE AppMain(Flag)

      USE UserApp

      IMPLICIT NONE

      INTEGER(4) :: rtnsts,Flag
      STRING     :: line
      OBJECT('System.Exception')                      se
      OBJECT('System.Threading.ThreadAbortException') te

      TRY

! Code will be added here......

        IF (IdeFlag.EQ.0) THEN                                  
           line   = ReadLine()
           rtnsts = IDERTN(2)
        END IF
        IF (IdeFlag.EQ.1) THEN
           rtnsts = IDERTN(0)
        END IF
        
      CATCH (te)

! User has pressed the 'Halt' button

      CATCH (se)

! Report exception in AppMain and terminate

        CALL EVTAPP(se)

      END TRY

  END SUBROUTINE AppMain
                                                                  

! Main Program

  PROGRAM MAIN

    USE UserApp

    IMPLICIT NONE

    EXTERNAL AppMain

! Local variables definition

    INTEGER(4) :: rtnsts
    STRING     :: line
    OBJECT('System.Exception')             se
    OBJECT('SciPlot.SPIde')                IdeForm
    OBJECT('System.Threading.ThreadStart') AppStart
                                                                  

! SciPlot SPIde Class Instantiation

    IdeFlag = 1
    IF (IdeFlag.EQ.0) THEN
       IdeForm = NEW@('SciPlot.SPIde',0)
    END IF
    IF (IdeFlag.EQ.1) THEN
       IdeForm = NEW@('SciPlot.SPIde',1)
    END IF

! Following fortran code fails to compile...

! AppStart = NEW@('System.Threading.ThreadStart',AppMain)

! Equivalent C# code

! public static ThreadStart AppStart = new ThreadStart(AppMain);

    TRY

! Start SPIde Control Form

      rtnsts = IDEBEG(AppStart)

      STOP

    CATCH (se)

! Report exception in Main Program

      CALL EVTAPP(se)

    ENDTRY

  END PROGRAM

If anyone has an idea how to code it, please help me.

F Vote

11 Jul 2007 6:07 #2042

I am not able to give a direct answer to your enquiry but here are some general points...

  1. Have you tried using CREATE_THREAD@ etc as described in the help file under .NET platform->.NET Programming->Threads?

  2. For multi-threading you need the DBK_LINK command line option /MULTI_THREADED. This option is also available with FTN95 but only has any effect when used with /LINK because it is simply passed on to DBK_LINK.

  3. If you think that FTN95 is not doing what it should then it is a good idea to post a complete short program that illustrates the problem so that we can try it out for you.

11 Jul 2007 3:40 #2045

Unfortunately, CREATE_THREAD@ creates a thread and starts it. I need to start the thread at a much later time, and so need to create a ThreadStart delegate that is initialized with the app to be started.

The problem I described only involves the FTN95 compiler, not the linker.

The 'Threads' FTN95 documentation states 'Althought it is possible to create and start a thread using calls to the .NET framework' . This is why I assumed I could use a ThreadStart delegate.

I will take your suggestion and attempt a very short and simple program to demonstrate the FTN95 compiler's handling of the ThreadStart delegate.

Thaks for the reply

11 Jul 2007 4:32 #2046

Paul,

Here is the short program which fails to compile:

 MODULE UserApp
    LIBRARY 'System.dll'
    LIBRARY 'System.Data.dll'
    LIBRARY 'System.Drawing.dll'
    LIBRARY 'System.Windows.Forms.dll'
    ASSEMBLY_EXTERNAL(name='System.Console.WriteLine') WriteLine
  END MODULE UserApp
  SUBROUTINE AppMain(AppStart)
      USE UserApp
      IMPLICIT NONE
      OBJECT('System.Exception') se
      OBJECT('System.Threading.ThreadStart') AppStart
      TRY
        CALL WriteLIne(' AppMain Entered')
      CATCH (se)
        CALL WriteLine(' Exception in AppMain')
      END TRY
  END SUBROUTINE AppMain
  PROGRAM MAIN
    USE UserApp
    IMPLICIT NONE
    EXTERNAL AppMain
    INTEGER(4) :: rtnsts
    STRING     :: line
    OBJECT('System.Exception')             se
    OBJECT('SciPlot.SPIde')                IdeForm
    OBJECT('System.Threading.ThreadStart') AppStart
                                                                  

! FTN95 fails to compile this code correctly

    AppStart = NEW@('System.Threading.ThreadStart',AppMain)

! Equivalent C# code ! public static ThreadStart AppStart = new ThreadStart(AppMain); TRY CALL AppMain(AppStart) STOP CATCH (se) CALL WriteLine(' Exception in Main Program') ENDTRY END PROGRAM

Thanks for looking at it.

Fred Vote

12 Jul 2007 6:38 #2047

I have not had chance to look at your code yet but here are some observations.

A delegate is equivalent in many ways to a function. The thread delegate is effectively the function that the thread runs to execute the process. Hence it is defined in the code. When you start a thread the delegate (thread function) is called.

In the Windows API you can use CreateThread to start a thread in a paused state but I cannot see the equivalent of this in .NET. There is Threading.Suspend but this is depreciated.

I suspect that for simplicity you should be using CREATE_THREAD@ and or CREATE_THREAD1@. Given time I guess I could work out how to do the same thing by using a Threading.Thread constructor but the result would be the same.

On the other hand I may be missing the point altogether.

12 Jul 2007 12:14 #2050

The point is: instantiating the StartThread object in the Fortran code allows it to be passed to a C# DLL as an argument. That C# DLL can then create an AppMain thread at any time, start it, and when it terminates (terminated threads cannot be started a second time), create another AppMain thread, and start it again at any time (on a button press). CREATE_THREAD@ forces all this control to happen right in the Fortran code. This is not where my application does it.

13 Jul 2007 1:52 #2060

As far as I can tell, what you are attempting is not possible because the delegate is a .NET object and you cannot match this with a Fortran subprogram. You can do something like this from C# but only in very limited way as illustrated by the callback functions in Visual ClearWin.

Here is my trial code which goes part of the way but fails to compile even before trying to match a delegate...

ASSEMBLY_EXTERNAL(NAME='System.Threading.Thread.Start') ThreadStart OBJECT('System.Threading.ThreadStart') threadDelegate OBJECT('System.Threading.Thread') newThread OBJECT('System.Object') workFunction workFunction = NEW@('System.Object') threadDelegate = NEW@('System.Threading.ThreadStart', workFunction) newThread = NEW@('System.Threading.Thread', threadDelegate) CALL ThreadStart(newThread)

You could try experimenting with this but my guess is that it is not going to work. FTN95 is not designed to handle this level of sophistication.

Please login to reply.