diff --git a/Code/Core/otbWrapperApplication.cxx b/Code/Core/otbWrapperApplication.cxx
index 96f45e1201acc3f08d7892fe870a6a76655977b7..83b45af4a840d20cd1e87e22eebcf4db9d7f637b 100644
--- a/Code/Core/otbWrapperApplication.cxx
+++ b/Code/Core/otbWrapperApplication.cxx
@@ -39,15 +39,80 @@ namespace Wrapper
 
 Application::Application()
  : m_Name(""),
-   m_Description("")
+   m_Description(""),
+   m_ThreadId1(0),
+   m_ThreadId2(0),
+   m_ThreadId3(0),
+   m_ThreadId4(0),
+   m_Thread1HasFinished(true),
+   m_Thread2HasFinished(true),
+   m_Thread3HasFinished(true),
+   m_Thread4HasFinished(true)
 {
   // Don't call Init from the constructor, since it calls a virtual method !
+  m_Threader = ThreaderType::New();
+  m_ProgressSourceList = ObjectListType::New();
 }
 
 Application::~Application()
 {
 }
 
+void
+Application
+::StartProcess1()
+{
+  m_ThreadId1 = m_Threader->SpawnThread(RunProcess1_static, this);
+}
+
+void
+Application
+::StopProcess1()
+{
+  m_Threader->TerminateThread(m_ThreadId1);
+}
+
+void
+Application
+::StartProcess2()
+{
+  m_ThreadId2 = m_Threader->SpawnThread(RunProcess2_static, this);
+}
+
+void
+Application
+::StopProcess2()
+{
+  m_Threader->TerminateThread(m_ThreadId2);
+}
+
+void
+Application
+::StartProcess3()
+{
+  m_ThreadId3 = m_Threader->SpawnThread(RunProcess3_static, this);
+}
+
+void
+Application
+::StopProcess3()
+{
+  m_Threader->TerminateThread(m_ThreadId3);
+}
+
+void
+Application
+::StartProcess4()
+{
+  m_ThreadId4 = m_Threader->SpawnThread(RunProcess4_static, this);
+}
+
+void
+Application
+::StopProcess4()
+{
+  m_Threader->TerminateThread(m_ThreadId4);
+}
 
 std::vector<std::string>
 Application::GetParametersKeys(bool recursive)
@@ -90,13 +155,33 @@ void Application::UpdateParameters()
 
 void Application::Execute()
 {
-  this->DoExecute();
+  //this->DoExecute();
+  std::cout<<"Application::Execute starts"<<std::endl;
+  this->StartProcess1();
+
+  if( m_ProgressSourceList->Size() == 0 )
+    {
+      this->StartProcess2();
+    }
+  std::cout<<"Application::Execute done"<<std::endl;
 }
 
 void Application::ExecuteAndWriteOutput()
 {
   this->Execute();
 
+  while( m_Thread2HasFinished == false || m_Thread2HasFinished == false)
+    {
+      this->Sleep(500);
+    }
+ 
+  this->StartProcess3();
+  this->StartProcess4();
+}
+
+
+void Application::DoWriteOutput()
+{
   std::vector<std::string> paramList = GetParametersKeys(true);
   for (std::vector<std::string>::const_iterator it = paramList.begin();
       it != paramList.end();
@@ -106,11 +191,74 @@ void Application::ExecuteAndWriteOutput()
       {
       Parameter* param = GetParameterByKey(*it);
       OutputImageParameter* outputParam = dynamic_cast<OutputImageParameter*>(param);
+      m_CurWriter = outputParam->GetWriter();
       outputParam->Write();
       }
     }
 }
 
+void Application::DoWatchExecute()
+{
+  std::cout<<"Application::DoWatchExecute starts"<<std::endl;
+  /*
+  double last = 0;
+  double updateThres = 0.01;
+  double current = -1;
+  */
+  unsigned int nbProcessDone = 0;  
+  unsigned int nbProcess( m_ProgressSourceList->Size() );
+  unsigned int nbCurProcess( nbProcess );
+
+  while ( nbProcessDone < nbProcess &&  m_Thread1HasFinished == false)
+    {
+      itk::OStringStream oss;
+      for( unsigned int i=0; i<nbProcess; i++ )
+        {
+          unsigned int progressPercent = static_cast<unsigned int>(m_ProgressSourceList->GetNthElement( i )->GetProgress()*100);
+          std::string stars(progressPercent, '*');
+          std::string blanks(100-progressPercent, ' ');
+          oss<< "\rProcessing progress " << i <<": " <<  progressPercent << "% [" << stars << blanks << "]\n" ;
+          //std::cout << m_ProgressSourceList->GetNthElement( i )->GetProgress() << std:endl;
+          //std::cout << "\rProcessing progress: " << progressPercent << "% [" << stars << blanks << "]" << std::flush;
+          if( m_ProgressSourceList->GetNthElement( i )->GetProgress()==1 )
+            {
+              nbProcessDone++;
+            }
+        }
+      std::cout << oss.str() << std::endl;//flush;
+      Sleep(500);
+      
+      /*
+        current = m_ProcessObject->GetProgress();
+        if (current - last > updateThres)
+        {
+        // Make the main fltk loop update progress fields
+        m_View->AwakeProgressFields(m_ProcessObject->GetProgress());
+        last = current;
+        }
+        }
+        // Sleep for a while
+        Sleep(500);
+        m_ProcessObject = m_Model->GetProcessObjectModel();
+      */
+    }  
+  std::cout<<"Application::DoWatchExecute done"<<std::endl;
+}
+
+void Application::DoWatchWrite()
+{
+  while( m_CurWriter.IsNotNull() && m_Thread3HasFinished==false )
+    {
+      unsigned int progressPercent = static_cast<unsigned int>(m_CurWriter->GetProgress()*100);
+      std::string stars(progressPercent, '*');
+      std::string blanks(100-progressPercent, ' ');
+      std::cout << "\rProcessing progress: " << progressPercent << "% [" << stars << blanks << "]" << std::endl;//flush;
+
+      Sleep(500);
+    }  
+}
+
+
 /* Enable the use of an optional parameter. Returns the previous state */
 void Application::EnableParameter(std::string paramKey)
 {
diff --git a/Code/Core/otbWrapperApplication.h b/Code/Core/otbWrapperApplication.h
index 68bfa7210f98b9a221beb6c609e633052cde7032..c5e2d77173c99d38dd26afb4ffbca19c344f19d3 100644
--- a/Code/Core/otbWrapperApplication.h
+++ b/Code/Core/otbWrapperApplication.h
@@ -22,6 +22,8 @@
 #include "otbMacro.h"
 #include "itkObject.h"
 #include "itkObjectFactory.h"
+#include "otbObjectList.h"
+#include "otbThreads.h"
 
 #include "otbWrapperTypes.h"
 #include "otbWrapperParameterGroup.h"
@@ -46,8 +48,8 @@ public:
   typedef itk::SmartPointer<Self> Pointer;
   typedef itk::SmartPointer<const Self> ConstPointer;
 
-  /** Defining ::New() static method */
-  //itkNewMacro(Self);
+  typedef ObjectList< itk::ProcessObject > ObjectListType;
+  typedef itk::MultiThreader ThreaderType;
 
   /** RTTI support */
   itkTypeMacro(Application,itk::Object);
@@ -246,6 +248,57 @@ public:
    */
   std::vector<std::string> GetParametersKeys(bool recursive = true);
 
+  /**
+   * Get the progress report sources.
+   */
+  itkSetObjectMacro( ProgressSourceList, ObjectListType );
+  itkGetObjectMacro( ProgressSourceList, ObjectListType );
+
+  void AddProgressSource( itk::ProcessObject *  obj )
+  {
+    m_ProgressSourceList->PushBack( obj );
+    this->Modified();
+  }
+
+  itk::ProcessObject * GetNthProgressSource( unsigned int i )
+  {
+    if( m_ProgressSourceList->Size() < i )
+      {
+        itkExceptionMacro( "invalid index "<<i<<". Only "<<m_ProgressSourceList->Size()<<" progress sources availbale." );
+      }
+    return m_ProgressSourceList->GetNthElement( i );
+  }
+  
+  /** 
+   * Multi thread methods 
+   */
+  void StartProcess1();
+  void StopProcess1();
+  void StartProcess2();
+  void StopProcess2();
+  void StartProcess3();
+  void StopProcess3();
+  void StartProcess4();
+  void StopProcess4();
+
+  void SetThreader(ThreaderType::Pointer threader)
+  {
+    m_Threader = threader;
+  }
+  ThreaderType::Pointer GetThreader()
+    {
+    return m_Threader;
+  }
+
+  itkGetConstMacro(Thread1HasFinished, bool);
+  itkSetMacro(Thread1HasFinished, bool);
+  itkGetConstMacro(Thread2HasFinished, bool);
+  itkSetMacro(Thread2HasFinished, bool);
+  itkGetConstMacro(Thread3HasFinished, bool);
+  itkSetMacro(Thread3HasFinished, bool);
+  itkGetConstMacro(Thread4HasFinished, bool);
+  itkSetMacro(Thread4HasFinished, bool);
+
 protected:
   /** Constructor */
   Application();
@@ -286,7 +339,101 @@ private:
   std::string m_Name;
   std::string m_Description;
   ParameterGroup::Pointer m_ParameterList;
+  ObjectListType::Pointer m_ProgressSourceList;
 
+
+ /** 
+   * Multi thread methods 
+   */
+  static ITK_THREAD_RETURN_TYPE RunProcess1_static(void * t)
+  {
+    struct itk::MultiThreader::      ThreadInfoStruct * pInfo = (itk::MultiThreader::ThreadInfoStruct *) (t);
+    Application::Pointer lThis = (Application*) (pInfo->UserData);
+    lThis->RunProcess1(t);
+    return 0;
+  }
+
+  
+  virtual void RunProcess1(void * itkNotUsed(t))
+  {
+    //itkExceptionMacro(<< "The RunProcess1 method has to be overloaded.");
+    m_Thread1HasFinished = false;
+    this->DoExecute();
+    m_Thread1HasFinished = true;
+  }
+  
+
+  static ITK_THREAD_RETURN_TYPE RunProcess2_static(void * t)
+  {
+    struct itk::MultiThreader::      ThreadInfoStruct * pInfo = (itk::MultiThreader::ThreadInfoStruct *) (t);
+    Application::Pointer lThis = (Application*) (pInfo->UserData);
+    lThis->RunProcess2(t);
+    return 0;
+  }
+
+  virtual void RunProcess2(void * itkNotUsed(t))
+  {
+    //itkExceptionMacro(<< "The RunProcess2 method has to be overloaded.");
+    m_Thread2HasFinished = false;
+    this->DoWatchExecute();
+    m_Thread2HasFinished = true;
+  }
+
+
+  static ITK_THREAD_RETURN_TYPE RunProcess3_static(void * t)
+  {
+    struct itk::MultiThreader::      ThreadInfoStruct * pInfo = (itk::MultiThreader::ThreadInfoStruct *) (t);
+    Application::Pointer lThis = (Application*) (pInfo->UserData);
+    lThis->RunProcess3(t);
+    return 0;
+  }
+
+  virtual void RunProcess3(void * itkNotUsed(t))
+  {
+    //itkExceptionMacro(<< "The RunProcess2 method has to be overloaded.");
+    m_Thread3HasFinished = false;
+    this->DoWriteOutput();
+    m_Thread3HasFinished = true;
+  }
+
+  static ITK_THREAD_RETURN_TYPE RunProcess4_static(void * t)
+  {
+    struct itk::MultiThreader::      ThreadInfoStruct * pInfo = (itk::MultiThreader::ThreadInfoStruct *) (t);
+    Application::Pointer lThis = (Application*) (pInfo->UserData);
+    lThis->RunProcess4(t);
+    return 0;
+  }
+
+  virtual void RunProcess4(void * itkNotUsed(t))
+  {
+    //itkExceptionMacro(<< "The RunProcess2 method has to be overloaded.");
+    m_Thread4HasFinished = false;
+    this->DoWatchWrite();
+    m_Thread4HasFinished = true;
+  }
+
+
+  void DoWatchExecute();
+  void DoWatchWrite();
+  void DoWriteOutput();
+
+  // Internal call to openthread::Thread::microSleep
+  // by the intermediate of the otb class Threads
+  static int Sleep(unsigned int microsec)
+  {
+    return Threads::Sleep(microsec);
+  }
+
+  ThreaderType::Pointer m_Threader;
+  int                   m_ThreadId1;
+  int                   m_ThreadId2;
+  int                   m_ThreadId3;
+  int                   m_ThreadId4;
+  bool                  m_Thread1HasFinished;
+  bool                  m_Thread2HasFinished;
+  bool                  m_Thread3HasFinished;
+  bool                  m_Thread4HasFinished;
+  itk::ProcessObject::Pointer m_CurWriter;
 }; //end class
 
 } // end namespace Wrapper
diff --git a/Code/Core/otbWrapperOutputImageParameter.h b/Code/Core/otbWrapperOutputImageParameter.h
index 79313d3d3db7ae6d34e5628ae26300e92b1ccbf6..58a35a28117f3791e69d7118e328f925352e37f9 100644
--- a/Code/Core/otbWrapperOutputImageParameter.h
+++ b/Code/Core/otbWrapperOutputImageParameter.h
@@ -39,6 +39,8 @@ public:
   typedef itk::SmartPointer<Self>       Pointer;
   typedef itk::SmartPointer<const Self> ConstPointer;
 
+  typedef otb::StreamingImageFileWriter<VectorImageType> WriterType;
+
   /** Defining ::New() static method */
   itkNewMacro(Self);
 
@@ -65,17 +67,17 @@ public:
 
   itkSetStringMacro(FileName);
   itkGetStringMacro(FileName);
+ 
+  itkGetObjectMacro( Writer, WriterType );
 
   void Write()
   {
     if (m_Image.IsNotNull())
       {
-      typedef otb::StreamingImageFileWriter<VectorImageType> WriterType;
-
-      WriterType::Pointer writer = WriterType::New();
-      writer->SetInput(m_Image);
-      writer->SetFileName(this->GetFileName());
-      writer->Update();
+      m_Writer = WriterType::New();
+      m_Writer->SetInput(m_Image);
+      m_Writer->SetFileName(this->GetFileName());
+      m_Writer->Update();
       }
   }
 
@@ -85,6 +87,7 @@ protected:
   {
     this->SetName("Output Image");
     this->SetKey("out");
+    m_Writer = WriterType::New();
   }
 
   /** Destructor */
@@ -93,6 +96,7 @@ protected:
 
   VectorImageType::Pointer m_Image;
   std::string m_FileName;
+  WriterType::Pointer m_Writer;
 
 private:
   OutputImageParameter(const Parameter &); //purposely not implemented
diff --git a/Example/otbRescale.cxx b/Example/otbRescale.cxx
index 41d088677c041dc87f9c1b1171ce4dbc0a6bcddf..c3935d04d24a11efd902a3fb4495f85918d947c1 100644
--- a/Example/otbRescale.cxx
+++ b/Example/otbRescale.cxx
@@ -53,6 +53,8 @@ private:
     SetDescription("Rescale the image between two given values.");
     m_RescaleFilter = RescaleImageFilterType::New();
     m_MinMaxFilter = MinMaxFilterType::New();
+
+    this->AddProgressSource(m_MinMaxFilter);
   }
 
   virtual ~Rescale()
@@ -76,7 +78,8 @@ private:
   }
 
   void DoExecute()
-  { 
+  {  
+    std::cout<<"rescale::DoExecute starts"<<std::endl;
     VectorImageType::Pointer inImage = GetParameterImage("in");
    
     std::cout<<"first step"<<std::endl;
@@ -104,6 +107,8 @@ private:
     
     SetParameterOutputImage("out", m_RescaleFilter->GetOutput());
     std::cout<<"output updated"<<std::endl;
+
+    std::cout<<"rescale::DoExecute starts"<<std::endl;
   }
   
   RescaleImageFilterType::Pointer m_RescaleFilter;
diff --git a/Testing/Python/PythonRescaleTest.py b/Testing/Python/PythonRescaleTest.py
index c2eaa0f6569c9e9d68fc17a2969084ae7a9a9ef2..af2a73c9aee3908b33588083e90613a0c6132842 100644
--- a/Testing/Python/PythonRescaleTest.py
+++ b/Testing/Python/PythonRescaleTest.py
@@ -5,9 +5,7 @@
 #
 from sys import argv
 import otbApplication as otb
-
 print "Available applications : " + str(otb.Registry.GetAvailableApplications())
-
 app = otb.Registry.CreateApplication("Rescale")
 print app.GetParametersKeys()
 
@@ -16,6 +14,7 @@ app.SetParameterString("in", argv[1])
 app.SetParameterFloat("outmin", 1)
 app.SetParameterFloat("outmax", 100)
 app.SetParameterString("out", argv[2] + ".tif")
+
 app.Execute()
   
 print dir(app)