【问题标题】:Start form in new thread and Raise events between them在新线程中启动表单并在它们之间引发事件
【发布时间】:2015-11-27 08:03:58
【问题描述】:

我尝试在新线程中启动表单(请参阅下面的代码架构)。 但表单显示后关闭。

Thread te;    
dia di = new dia();
private static Thread te;
public static event AddingNewEventHandler tempchange;
public delegate void AddingNewEventHandler(int sender, EventArgs e);
static void Main(string[] args)
{    
   di.Coneig += new Config.AddingNewEventHandler(config);
   te = new Thread(new ThreadStart(di.Show));     
   te.Start();    
   while(true)
   {
     //async code to Form
   }
}

public static void config(int[] sender, EventArgs e)
{
    //Edit some values in the main(Class variables)
}

【问题讨论】:

  • 因为程序在主线程中结束。你必须以某种方式在主线程中等待。
  • “我尝试在新线程中启动一个表单” - 为什么呢?
  • 阅读这个答案:stackoverflow.com/a/428556/1506454,它可能会有所帮助(虽然问题不是重复的)
  • 在新线程中运行表单是非常不寻常的——这有什么特殊原因吗?你可能会发现,如果你澄清你的理由,你会得到一些很好的答案,这将使你避免整个“单独线程上的表格”业务。

标签: c# .net multithreading winforms


【解决方案1】:
Thread te;    
dia di = new dia();

static void Main(string[] args)
{    
   te = new Thread(new ThreadStart(di.Show));     
   te.Start();    
   Console.ReadKey();
}

编辑:

这个我检查过..

    static void Main(string[] args)
    {
       Form di = new Form();


        Thread te = new Thread(() => 
        {
            Application.EnableVisualStyles();
            Application.Run(di);
        });
        te.Start();
    }

【讨论】:

  • 它不应该停止主程序,因为还有一些其他代码与表单异步运行。
  • 效果更好,但我订阅了一些在 Main 中触发的事件。事件无法再到达 di 形式。
  • @Benedikt 你的意思是你需要从窗口触发事件,这应该改变主变量??
  • 正确。这就是表单应该做的事情。
  • @Benedikt 你能告诉我你需要在主程序中改变什么样的变量吗?这样我就可以改变我的程序。我在我的自定义程序中得到了结果。
【解决方案2】:

试试这个:

te = new Thread(new ThreadStart(()=>di.ShowDialog()));

我不确定它的用途,但它应该可以工作。

线程将保持活动状态,直到您关闭表单。

【讨论】:

    【解决方案3】:

    你可以使用

    te.Join();
    

    作为 Main 结束前的最后一行。这应该可以正常工作。

    更详细的解释应该如何

    当您启动一个 Windows 窗体应用程序时,您启动了一个 GUI/事件/主线程。在 winforms 库中的某处可视化如下所示的无限 while 循环

    Queue<EventArgs> EventQueue = new Queue<EventArgs>();
    while (!StopRequested) {
        if (EventQueue.Any())
            ProcessEvent(EventQueue.Dequeue());
        Thread.CurrentThread.Sleep(100);
    }
    

    所有控件都在这个线程中创建,所有事件都在这个线程中触发。现在,由于您的代码中不存在此代码,因此获得 GUI/事件相关服务的唯一方法是发布到此 EventQueue

    现在有了这个背景,让我们来看看你的情况。

    引发和处理事件

    一个表单/线程的引发和处理事件的工作方式与多个表单/线程的工作方式完全相同。请记住,引发事件只是发布到 EventQueue 的行为,并且事件处理程序的调用发生在 ProcessEvents

    表单生命周期

    在典型的 WinForms 应用程序中,您可以使用如下所示的行来告诉系统创建一个 EventQueue 并将其生命周期与表单的生命周期相关联。

    Application.Run(new Form());
    

    你可以使用

    new Form().Show()
    

    开始将事件泵入EventQueue,从而显示表单,但请记住,一旦您的应用程序的主线程到达Main 的末尾,EventLoop 将被突然终止。

    因此关闭此表单将导致您的应用程序停止,反之亦然。

    您的情况

    我强烈建议您从主线程启动表单,然后在新线程上完成其他工作。我看到您将发件人用作intint[],这是一个问题。如果我需要实现相同的目标,以下是我将如何编写。我尽量保持它与您的样本相似

    class Program {
        static Form1 frm;
    
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
    
            frm = new Form1();
            frm.Test += TestEventHandler;
    
            new Thread(new ThreadStart(DoAsyncProcessing)).Start();
    
            Application.Run(frm);
        }
    
        static void DoAsyncProcessing() {
            // async code goes here
            Thread.Sleep(5000);
    
            // raise the event
            frm.RaiseTestEvent("Test Event Data");
        }
    
        static void TestEventHandler(object sender, TestEventArgs e) {
            System.Diagnostics.Debug.WriteLine("Received test event with data: " 
                + e.EventData);
        }
    }
    
    public partial class Form1 : Form {
        public event EventHandler<TestEventArgs> Test;
    
        public Form1() {
            InitializeComponent();
        }
    
        public void RaiseTestEvent(string eventData) {
            var arg = new TestEventArgs() { EventData = eventData };
            OnTest(arg);
        }
    
        protected virtual void OnTest(TestEventArgs e) {
            EventHandler<TestEventArgs> handler = Test;
            if (handler != null)
                handler(this, e);
        }
    }
    
    public class TestEventArgs : EventArgs {
        public object EventData { get; set; }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多