C# 如何从套接字线程创建Window.Forms.Form
我正在编写一个小应用程序,它将作为NLog网络目标的端点(通过TCP发送调试消息)。该应用程序使用套接字创建服务器并接受连接。此应用程序是无窗口的,使用NotifyIcon和ApplicationContext在系统托盘中启动。应用程序侦听端口,当它从唯一端点接收到第一条消息时,它将创建一个新窗口并显示它(这些窗口将包含实际的调试消息)。我已经能够让窗口显示,但它的显示就像挂起一样,我猜这是因为它是从套接字创建的不可见线程中创建的 如何从test_ClientConnected事件正确创建新的Windows.Form 这是ApplicationContext代码C# 如何从套接字线程创建Window.Forms.Form,c#,multithreading,forms,sockets,applicationcontext,C#,Multithreading,Forms,Sockets,Applicationcontext,我正在编写一个小应用程序,它将作为NLog网络目标的端点(通过TCP发送调试消息)。该应用程序使用套接字创建服务器并接受连接。此应用程序是无窗口的,使用NotifyIcon和ApplicationContext在系统托盘中启动。应用程序侦听端口,当它从唯一端点接收到第一条消息时,它将创建一个新窗口并显示它(这些窗口将包含实际的调试消息)。我已经能够让窗口显示,但它的显示就像挂起一样,我猜这是因为它是从套接字创建的不可见线程中创建的 如何从test_ClientConnected事件正确创建新的W
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());
}
}
静态类程序
{
///
///应用程序的主要入口点。
///
[状态线程]
静态void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
运行(新的NLApplicationContext());
}
}
您的想法是正确的,不要在套接字线程中创建表单,而是移动代码以创建表单并将其显示到方法中,然后调用方法以在UI线程上执行它。您可以将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();
}
终于找到了一种不同的方法,允许我在主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
}
}
类NLApplicationContext:ApplicationContext
{
列出_connections;//暂时临时存储
同步上下文测试;
公共NLApplicationContext()
{
测试=SynchronizationContext.Current;
_连接=新列表();
NLServer test=新的NLServer();
test.ClientConnected+=test\u ClientConnected;
test.Start();
}
无效测试\u客户端已连接(对象发送方)
{
测试。Post(显示表单、发送者);
}
私有void显示表单(对象发送方)
{
Form2 newForm=新Form2((NLClient)发送方);
newForm.Show();
_connections.Add(newForm);//查找更好的存储/排序
}
}
使用SynchronizationContext允许我发回创建它的线程。好的,我是否创建此调度程序?我找到的唯一引用是在WPF中使用的,可能我看错了。Hrmm…这确实有效,但是我需要它在主UI线程上运行,因为我在那里存储表单实例,表单列表,因为可能有一些连接。将此标记为应答,因为它是最接近的一个。你给我指出了正确的方向,谢谢。