如何从Socket Thread创建Window.Forms.Form

时间:2013-01-05 14:55:29

标签: c# multithreading forms sockets applicationcontext

我正在编写一个小应用程序,它将成为NLog网络目标的终端(通过TCP发送调试消息)应用程序使用套接字创建服务器并接受连接。此应用程序是无窗口的,使用NotifyIcon和ApplicationContext在系统托盘中启动。应用程序侦听端口,当它从唯一的端点收到它的第一条消息时,它将创建一个新窗口并显示它(这些窗口将包含实际的调试消息)我已经能够显示窗口但它正在显示好像它已挂起,我猜它是因为它是从套接字创建的不可见线程创建的。

如何从test_ClientConnected事件中正确创建新的Windows.Form?

这是ApplicationContext代码

public NLApplicationContext()
    {
        NLServer test = new NLServer();
        test.ClientConnected += test_ClientConnected;
        test.Start();
    }

    void test_ClientConnected(object sender)
    {
        Form2 newForm = new Form2((NLClient)sender);
        newForm.Invoke(new MethodInvoker(() => {newForm = new Form2((NLClient)sender);}));
        newForm.Invoke(new MethodInvoker(() => { newForm.Show(); }));

        Console.WriteLine("Connected");
        /*if (((NLClient)sender).testy.InvokeRequired)
        {
            ((NLClient)sender).testy.BeginInvoke(new MethodInvoker(((NLClient)sender).testy.Show()));
            return;
        }*/
    }

这是程序入口点

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new NLApplicationContext());
    }
}

3 个答案:

答案 0 :(得分:0)

你有正确的想法,而不是在套接字线程中创建表单,移动代码来创建表单并将其显示到方法中,然后Dispatcher.Invoke在UI线程上执行它的方法。 / p>

答案 1 :(得分:0)

您可以将UI工作委托给一个单独的线程,如下所示:

   void test_ClientConnected(object sender)
   {
     Thread displayFormThread = new Thread(ParameterizedThreadStart(DisplayForm));
     displayFormThread.Start(sender);
   }

   private void DisplayForm(object sender)
   {
    Form2 newForm = new Form2((NLClient)sender);
    newForm.Show();
   }

答案 2 :(得分:0)

最后想出了一种允许我在主UI线程中创建表单的不同方式。

NLApplicationContext

class NLApplicationContext : ApplicationContext 
{
    List<Form2> _connections;  // Temp storage for now
    SynchronizationContext testS;


    public NLApplicationContext()
    {
        testS = SynchronizationContext.Current;
        _connections = new List<Form2>();

        NLServer test = new NLServer();
        test.ClientConnected += test_ClientConnected;
        test.Start();
    }

    void test_ClientConnected(object sender)
    {
        testS.Post(DisplayForm, sender);
    }

    private void DisplayForm(object sender)
    {
        Form2 newForm = new Form2((NLClient)sender);
        newForm.Show();
        _connections.Add(newForm);  //Find better storage/sorting
    }
}

使用SynchronizationContext允许我回发到它创建的线程。