none
Multihilo llamar otro proyecto desde el principal RRS feed

  • Pregunta

  • Hola amigos como estan, hoy ya entendi un poco el funcionamiento de multihilo pero ahora me encuentro con un problema y es que no se como hacer que funcione el llamado a otro proyecto de una misma solucion ya que me da una alerta que debe ser STA.

    ThreadStart ParaleloBarra = new ThreadStart(tareaBarra);
                    Thread hilo = new Thread(ParaleloBarra);
                    hilo.Start();

    esta parte esta bien pero al el llamar este codigo

     proceso1 = new ProgressBar();
                proceso1.Show();

    entonces me dice que debe ser stat y no se como ponerlo static ya que contiene una interfaz grafica

    namespace Capture_Extractor
    {
       
        public partial class ProgressBar : Window
        {
            System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
            public ProgressBar()
            {
                InitializeComponent();
                barra();
                t.Interval = 20000; // specify interval time as you want
                t.Tick += new EventHandler(timer_Tick);
                t.Start();
    
            }
    ...

    que deberia hacer para llevar a cabo esa accion?

    miércoles, 10 de enero de 2018 3:25

Respuestas

  • La interfaz de Windows Forms es mono-hilo. No se puede acceder a la interfaz gráfica desde un hilo distinto del que la creó. Si necesitas lanzar un proceso de cálculo en un hilo secundario, puede hacerse a condición de que ese hilo no acceda a la pantalla. Si el hilo secundario necesita mostrar algo en pantalla, tiene que trasladar esa operación al hilo principal. Eso se consigue llamando al método Invoke de cualquier control, incluyendo el propio Form.
    miércoles, 10 de enero de 2018 7:53
    Moderador
  • Buenos días, 

    primero decirte que para lo que pretenders realziar quizás uses el control de formulario BackGroundWorker

    No obstante creo que es posible hacer lo que pretendes (entiendo que es ir haciendo algo cada 2 segundos) al cargar la clase ProgressBar) dicho esto:

    Thread thread = new Thread(()=> { tareaBarra(); });    
    
    thread.SetApartmentState(ApartmentState.STA);
    
    thread.Start();

    Aqui tienes como llamar com oSTA a tu hilo.

    Lo que yo cambiaría seria el timer por un bucle :

      public partial class ProgressBar : Window
        {
            System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
            public ProgressBar()
            {
                InitializeComponent();
                barra();
                bool terminar=false;
                while(!terminar)
                {
                    terminar=this.TareaTimer();
                    Thread.Sleep(20000);
                }
    
            }
    
            private bool TareaTimer()
            { ..... }

    Saludos


    • Editado vyrcyrus_ miércoles, 10 de enero de 2018 8:20
    • Propuesto como respuesta vyrcyrus_ miércoles, 10 de enero de 2018 8:20
    • Marcado como respuesta Pablo RubioModerator lunes, 15 de enero de 2018 16:24
    miércoles, 10 de enero de 2018 8:09

Todas las respuestas

  • La interfaz de Windows Forms es mono-hilo. No se puede acceder a la interfaz gráfica desde un hilo distinto del que la creó. Si necesitas lanzar un proceso de cálculo en un hilo secundario, puede hacerse a condición de que ese hilo no acceda a la pantalla. Si el hilo secundario necesita mostrar algo en pantalla, tiene que trasladar esa operación al hilo principal. Eso se consigue llamando al método Invoke de cualquier control, incluyendo el propio Form.
    miércoles, 10 de enero de 2018 7:53
    Moderador
  • Buenos días, 

    primero decirte que para lo que pretenders realziar quizás uses el control de formulario BackGroundWorker

    No obstante creo que es posible hacer lo que pretendes (entiendo que es ir haciendo algo cada 2 segundos) al cargar la clase ProgressBar) dicho esto:

    Thread thread = new Thread(()=> { tareaBarra(); });    
    
    thread.SetApartmentState(ApartmentState.STA);
    
    thread.Start();

    Aqui tienes como llamar com oSTA a tu hilo.

    Lo que yo cambiaría seria el timer por un bucle :

      public partial class ProgressBar : Window
        {
            System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
            public ProgressBar()
            {
                InitializeComponent();
                barra();
                bool terminar=false;
                while(!terminar)
                {
                    terminar=this.TareaTimer();
                    Thread.Sleep(20000);
                }
    
            }
    
            private bool TareaTimer()
            { ..... }

    Saludos


    • Editado vyrcyrus_ miércoles, 10 de enero de 2018 8:20
    • Propuesto como respuesta vyrcyrus_ miércoles, 10 de enero de 2018 8:20
    • Marcado como respuesta Pablo RubioModerator lunes, 15 de enero de 2018 16:24
    miércoles, 10 de enero de 2018 8:09
  • dejare el codigo completo por que en efecto uso el backworked

    namespace Capture_Extractor
    {
       
        public partial class ProgressBar : Window
        {
            System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
            public ProgressBar()
            {
                InitializeComponent();
                barra();
                t.Interval = 20000; // specify interval time as you want
                t.Tick += new EventHandler(timer_Tick);
                t.Start();
    
            }
    
            void timer_Tick(object sender, EventArgs e)
            {
                barra();
            }
    
            void barra()
            {
                this.pgbEstatus.Value = 0;
                BackgroundWorker worker = new BackgroundWorker();
                worker.WorkerReportsProgress = true;
                worker.DoWork += Worker_DoWork;
                worker.ProgressChanged += Worker_ProgressChanged;
                worker.RunWorkerAsync();
            }
    
    
            private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                this.pgbEstatus.Value = e.ProgressPercentage;
            }
    
            private void Worker_DoWork(object sender, DoWorkEventArgs e)
            {
                for (int i = 0; i < 100; i++)
                {
                    (sender as BackgroundWorker).ReportProgress(i + 1);
                    Thread.Sleep(200);
                }
            }
        }
    }
    esto es una barra de progreso, q quiero que se muestre en el proyecto primero cuando se le de la orden o en este caso, yo ejecuto al programa principal y el en una face llama la barra.

    • Propuesto como respuesta vyrcyrus_ miércoles, 10 de enero de 2018 14:04
    miércoles, 10 de enero de 2018 13:10
  • Por lo que puedo a ver asi en una mirada tienes ahi un buen cacao:

    Te muestro como haria lo que creo que quieres hacer solo con un timer.

    public partial class ProgressBar : Window  // Entiendo que debe ser :Form
    {
        private System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
    
        // Constructor
        public ProgressBar()
        {
            InitializeComponent();
            this.InitBarra();
            // Configruo timer y arranco
            this.t.Interval = 200;  // Aqui es el itnervalo de pintado de la barra
            this.t.Tick += new EventHandler(timer_Tick);
            this.t.Start();
    
        }
    
        private void InitBarra()
        {
            this.pgbEstatus.Max = 100;
            this.pgbEstatus.Min = 0;
            this.pgbEstatus.Value = 0;
        }
    
    
        void timer_Tick(object sender, EventArgs e)
        {
                // mientras no llegue a 100 cada vez que entre sube // Si llega a 100 paro timer.
                if (this.pgbEstatus.Value < 100)
                {
                    this.pgbEstatus.Value += 1;
                }
                else
                {
                    this.t.Enabled = false;
                    this.t.Stop();
                }
        }
    
    
    }

    miércoles, 10 de enero de 2018 14:03
  • te pregunto , ese planteamiento que haces es para volerlo STA? porque solament enecisto volverlo asi, ya que el asi como lo tengo funciona bien si lo ejecuto aparte de manera individual
    jueves, 11 de enero de 2018 4:28
  • Diria que no es para volverlo STA sino que siempre estoy en el Main Thread programado de esa forma. Ya que el timer tal como defino no se ejecuta en un thread diferente.
    jueves, 11 de enero de 2018 7:35
  • ah exacto, como lo volverias STA? ya que en efecto tienes razon esta en un main principal osea en otro proyecto, y cuando lo ejecuto lo hago directamente del exe que crea ahi radica mi rollo
    jueves, 11 de enero de 2018 13:45
  • en el program.cs en tu proyecto busca el main

    y encima de la firma del function void main(... añade el atributo de STA.

    [STAThread]

    void main ...

    recuerdo que era algo asi.

    jueves, 11 de enero de 2018 17:07
  • probare de inmediato y si funciona te cuento

    jueves, 11 de enero de 2018 17:50
  • la solucion era la siguiente , en la funcion de la creacion del llamado del otro proyecto colocar el esto.

     private void TareaBarra()
            {
                Dispatcher.Invoke(() => {
                    proceso1 = new ProgressBar();
                    proceso1.Show();
                });
               
            }

    dispatcher invoke y listo gracias de todos modos a sus respuestas.

    sábado, 20 de enero de 2018 19:36