C# 通过 TCP 接收远程命令并在 WinForm 上调用它们(多线程)
我有一个控制台,我想用它来调用另一台计算机上的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我建议使用 WCF 代替; WCF 中有一个选项可以自动同步到主机的
SynchronizationContext
。下一个最佳选择是使用自动同步套接字对象,例如 Nito.Async 中的对象。
第三种选择是保留 .NET
Socket
类,但当您需要执行 UI 更新时,使用调度到 UI 线程的Task
(TaskScheduler.FromCurrentSynchronizationContext< /代码>)。
Task
和TaskScheduler
内置于 .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 aTask
scheduled to the UI thread (TaskScheduler.FromCurrentSynchronizationContext
).Task
andTaskScheduler
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 useSynchronizationContext
directly for updating the UI.代替
MethodInfo.Invoke
,使用:Control
类的Invoke()
方法是据我所知,唯一的方法在调用控件上的方法时执行正确的线程同步。Instead of
MethodInfo.Invoke
, use: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.