none
Зависает форма созданная в program.cs RRS feed

  • Вопрос

  • using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Threading;
    
    namespace WindowsFormsApplication1
    {
      static class Program
      {
        static void MainThread()
        {
          Form1 form = new Form1();
          form.Show();
    
          while (true)
          {
            // цикл потока
          }
        }
    
        class MyContext : ApplicationContext
        {
          public MyContext()
          {
            Thread th = new Thread(new ThreadStart(MainThread));
            th.Start();
            
            Form2 form = new Form2();
            form.Show();
          }
        }
    
        [STAThread]
        static void Main()
        {
          MyContext context = new MyContext();
          Application.Run(context);
        }
      }
    }
    

    Это program.cs от обычного проекта, тока я его изменил

    Form1 и Form2 пустые формы.

    Вопрос такой. Почему Form2 создается и работает нормально, а Form1 рисуется и зависает. По сути мне Form2 и не нужна.

    Может это и изврат. Но все же. Смысл в том что-бы окно создавалось и появлялось в потоке (при необходимости). Поток работает с сокетами и при получении сообщения должно выскакивать окно.

    • Перемещено Tagore Bandlamudi 1 октября 2010 г. 21:40 MSDN Forums consolidation (От:Visual C#)
    21 июля 2010 г. 13:01

Ответы

  • >> Все формы работает отдельно каждая в своем потоке, так?

    Гы. Нет. В вашем коде все формы работают в одном большом потоке, в котором был запущен метод Application.Run в program.cs.

    Итак,  как было бы правильно решить вашу задачу в первом посте (если я правильно понял вашу задачу, хотя суть одна и таже):

    using System.Threading;
    
    namespace Sample
    {
     public partial class Form1 : Form
     {
     Thread thread;
     Boolean Loop = false; 
     private void Form1_Load(Object sender, EventArgs e)
     {
      this.thread = new Thread(new ThreadStart(Run));
      this.Loop = true;
      this.thread.Start( );
     }
     
     private void Run()
     {
      while (this.Loop)
      {
      // Вот только тут что-то выполняется в потоке (видать какая-то работа с сокетами)
      // Если получили сообщение, то
      this.ShowMessage("Я чего-то получил.");
      }
     }
     
     delegate void ShowMessageHandler(String msg);
    
     private void ShowMessage(String msg)
     {
      if (this.InvokeRequired)
      {
      ShowMessageHandler d = new ShowMessageHandler(this.ShowMessage);
      this.Invoke(d, new Object[ ] { msg });
      }
      else
      {
      Form2 frm = new Form2( );
      frm.textBox1.Text = msg; // или куда у вас там выводится сообщение
      frm.Show( );
      }
     }
     }
     }
    }

     

    Можно было бы проще с Invoke сделать (без отдельного метода), но если учиться, то полностью.

    Код писал здесь и не проверял, так что возможны опечатки (описки).

    На будущее, почитайте тут: http://www.rsdn.ru/article/dotnet/CSThreading1.xml и тут: http://rsdn.ru/article/dotnet/CSThreading2.xml

    • Помечено в качестве ответа Игорь П 22 июля 2010 г. 8:22
    22 июля 2010 г. 7:36

Все ответы

  • Потому что Формы однопоточные и никаких действий с ними на других потоках производить нельзя.

    Вместо того чтоб созадавать форму на другом потоке следует выполнять работу на другом потоке чтоб не блокировать форму. Для обновления формы при этом потребуется использовать Control.Invoke().


    This posting is provided "AS IS" with no warranties, and confers no rights.
    21 июля 2010 г. 16:20
    Модератор
  • Все равно не понятно. Почему тогда такой код прекрасно работает. При нажатии на кнопку создается форма Form2, и не зависает. и так много раз. Все формы работает отдельно каждая в своем потоке, так? Не зависимо от формы в которой я их создал. В предыдущем коде никаких действий с формой я не проводил. Я ее только создаю.

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication2
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
          Form2 form = new Form2();
          form.Show();
        }
      }
    }
    
    

     

    22 июля 2010 г. 5:24
  • >> Все формы работает отдельно каждая в своем потоке, так?

    Гы. Нет. В вашем коде все формы работают в одном большом потоке, в котором был запущен метод Application.Run в program.cs.

    Итак,  как было бы правильно решить вашу задачу в первом посте (если я правильно понял вашу задачу, хотя суть одна и таже):

    using System.Threading;
    
    namespace Sample
    {
     public partial class Form1 : Form
     {
     Thread thread;
     Boolean Loop = false; 
     private void Form1_Load(Object sender, EventArgs e)
     {
      this.thread = new Thread(new ThreadStart(Run));
      this.Loop = true;
      this.thread.Start( );
     }
     
     private void Run()
     {
      while (this.Loop)
      {
      // Вот только тут что-то выполняется в потоке (видать какая-то работа с сокетами)
      // Если получили сообщение, то
      this.ShowMessage("Я чего-то получил.");
      }
     }
     
     delegate void ShowMessageHandler(String msg);
    
     private void ShowMessage(String msg)
     {
      if (this.InvokeRequired)
      {
      ShowMessageHandler d = new ShowMessageHandler(this.ShowMessage);
      this.Invoke(d, new Object[ ] { msg });
      }
      else
      {
      Form2 frm = new Form2( );
      frm.textBox1.Text = msg; // или куда у вас там выводится сообщение
      frm.Show( );
      }
     }
     }
     }
    }

     

    Можно было бы проще с Invoke сделать (без отдельного метода), но если учиться, то полностью.

    Код писал здесь и не проверял, так что возможны опечатки (описки).

    На будущее, почитайте тут: http://www.rsdn.ru/article/dotnet/CSThreading1.xml и тут: http://rsdn.ru/article/dotnet/CSThreading2.xml

    • Помечено в качестве ответа Игорь П 22 июля 2010 г. 8:22
    22 июля 2010 г. 7:36
  • Спасибо. Примерно это мне и надо было.

    Если я в потоке вместо

    this.ShowMessage("Я чего-то получил.");

    ставлю

    Form2 frm = new Form2();

    frm.Show();

    форма открывается, но зависает, при этом через ShowDialog() форма работает нормально, но тогда поток останавливается пока не закрою форму, а не хотелось бы.

    Спасибо. Буду пробовать.

    22 июля 2010 г. 8:36
  • Ну вам же Ilya Tumanov уже писал:

    >> Вместо того чтоб созадавать форму на другом потоке следует выполнять работу на другом потоке чтоб не блокировать форму. Для обновления формы при этом потребуется использовать Control.Invoke().

    И в моем примере форма открывается используя Invoke. А вы всё равно в потоке создаете форму.

    Вам не нужно убирать метод this.ShowMessage("Я чего-то получил.");, вам лучше будет немножко подправить сам метод, если необходимо (другие параметры передавать (если так, то подправьте delegate void ShowMessageHandler(String msg); и сам Invoke), если нужно что-то делать с отображаемой формой, то подкорректируйте код после 'else' в ShowMessage).

    В таком случае при frm.Show( ); форма не будет зависать, и поток не приостановиться.

    22 июля 2010 г. 23:42