C# 通过 TCP 接收远程命令并在 WinForm 上调用它们(多线程)

发布于 2024-09-16 12:38:02 字数 2015 浏览 2 评论 0原文

我有一个控制台,我想用它来调用另一台计算机上的 WinForm 上的命令(尽管我正在通过 localhost 测试它)。

当表单启动时,它会实例化 CommandListener 以通过 TCP 接收命令。每当我尝试在没有单独线程的情况下实例化它时,winform 根本不显示,因此我使用“初始化”在单独的线程上运行它。

    public CommandListener(Form client)
    {
        this.ClientControl = client;

        Socket CommandSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPAddress ipa = IPAddress.Loopback;
        IPEndPoint ipe = new IPEndPoint(ipa, 23120);

        CommandSocket.Bind(ipe);
        CommandSocket.Listen(1);

        Thread RemoteCommandListener = new Thread(new ParameterizedThreadStart(Initialize));
        RemoteCommandListener.Start(CommandSocket);

    }

    private void Initialize(object obj)
    {
        Socket CommandSocket = (Socket)obj;

        while (true)
        {
            allDone.Reset();
            CommandSocket.BeginAccept(new AsyncCallback(AcceptCallback), CommandSocket);
            allDone.WaitOne();
        }
    }

不幸的是,如果我确实使用单独的线程,当尝试在 winform 上调用命令时,我会收到“跨线程操作无效”错误。

            int bytesRead = Master.EndReceive(ar);
            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(state.Buffer, 0, bytesRead));

                command = state.sb.ToString();
                if (command.IndexOf("Write") > -1)
                {
                    try
                    {
                        MethodInfo method = typeof(Multiboxxy).GetMethod(command);
                        method.Invoke(ClientControl, new object[] { "Success!" });
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.InnerException.Message);
                    }
                }
                else
                {
                    Master.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0,
                       new AsyncCallback(ReadCallback), state);
                }
            }

I have a console that I want to use to invoke commands on a WinForm in another computer (I'm testing it through localhost though).

When the form starts, it instantiates the CommandListener to receive commands over TCP. Whenever I attempt to instantiate it without a separate thread, the winform doesn't display at all, so I used "Initialize" to run it on a separate thread.

    public CommandListener(Form client)
    {
        this.ClientControl = client;

        Socket CommandSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPAddress ipa = IPAddress.Loopback;
        IPEndPoint ipe = new IPEndPoint(ipa, 23120);

        CommandSocket.Bind(ipe);
        CommandSocket.Listen(1);

        Thread RemoteCommandListener = new Thread(new ParameterizedThreadStart(Initialize));
        RemoteCommandListener.Start(CommandSocket);

    }

    private void Initialize(object obj)
    {
        Socket CommandSocket = (Socket)obj;

        while (true)
        {
            allDone.Reset();
            CommandSocket.BeginAccept(new AsyncCallback(AcceptCallback), CommandSocket);
            allDone.WaitOne();
        }
    }

Unfortunately, if I do use a separate thread, I receive "cross thread operation not valid" as an error when attempting to invoke the command on the winform.

            int bytesRead = Master.EndReceive(ar);
            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(state.Buffer, 0, bytesRead));

                command = state.sb.ToString();
                if (command.IndexOf("Write") > -1)
                {
                    try
                    {
                        MethodInfo method = typeof(Multiboxxy).GetMethod(command);
                        method.Invoke(ClientControl, new object[] { "Success!" });
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.InnerException.Message);
                    }
                }
                else
                {
                    Master.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0,
                       new AsyncCallback(ReadCallback), state);
                }
            }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽清梦 2024-09-23 12:38:02

我建议使用 WCF 代替; WCF 中有一个选项可以自动同步到主机的 SynchronizationContext

下一个最佳选择是使用自动同步套接字对象,例如 Nito.Async 中的对象。

第三种选择是保留 .NET Socket 类,但当您需要执行 UI 更新时,使用调度到 UI 线程的 Task (TaskScheduler.FromCurrentSynchronizationContext< /代码>)。 TaskTaskScheduler 内置于 .NET 4.0 中,并且是 可在 .NET 3.5 的库中使用

第四个选项是保留 .NET Socket 类并直接使用 SynchronizationContext 来更新 UI。

I recommend using WCF instead; there is an option in WCF to synchronize automatically to the SynchronizationContext of the host.

The next-best option is to use automatically-synchronizing socket objects such as those in Nito.Async.

A third option is to keep the .NET Socket class but when you need to do UI updates, use a Task scheduled to the UI thread (TaskScheduler.FromCurrentSynchronizationContext). Task and TaskScheduler are built into .NET 4.0 and are available in a library for .NET 3.5.

A fourth option is to keep the .NET Socket class and use SynchronizationContext directly for updating the UI.

梓梦 2024-09-23 12:38:02

代替 MethodInfo.Invoke,使用:

// somewhere, define a delegate type for the invoked method (e.g. 'InvokerDelegate')

if (ClientControl.InvokeRequired)
    ClientControl.Invoke(Delegate.CreateDelegate(typeof(InvokerDelegate), ClientControl, method), "Success!");
else
    method.Invoke(ClientControl, new object[] { "Success!" });

Control 类的 Invoke() 方法是据我所知,唯一的方法在调用控件上的方法时执行正确的线程同步。

Instead of MethodInfo.Invoke, use:

// somewhere, define a delegate type for the invoked method (e.g. 'InvokerDelegate')

if (ClientControl.InvokeRequired)
    ClientControl.Invoke(Delegate.CreateDelegate(typeof(InvokerDelegate), ClientControl, method), "Success!");
else
    method.Invoke(ClientControl, new object[] { "Success!" });

The Control class' Invoke() method is, to the best of my knowledge, the only way to perform proper thread synchronization when calling methods on controls.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文