C# 如何在单独的 class 和线程中从静态方法更改 textbox.Text
C# How can I change textbox.Text from a static method in a separate class and thread
所以我遇到的问题是我想在 Form1 上设置 textbox.Text。我很快发现线程安全,我认为我的代码解决了这个问题。我面临的下一个问题是我的客户编码的方式设置文本的方法必须是静态的,我不知道该怎么做。当然,除非我在 AsyncClient class 中的客户端方法不必是静态的,如果是这种情况,并且由于我缺乏知识,那就太好了。
正如您可能会说的那样,我正在为客户重新设计 Microsoft 的模板。这主要是因为我是一名大学生,目前只是用它来学习。
如果这个问题已经存在,我也想提前道歉,但是当我看的时候我找不到任何足够具体的问题来解决我的问题。
这是代码的顶部,去掉了命名空间。我会稍微拆分一下,只关注我谈到的部分。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket client;
public delegate void setTextCallback(string text);
public void setText(string text)
{
if (this.txtLog.InvokeRequired)
{
// Different thread, use Invoke.
setTextCallback d = new setTextCallback(FinishSetText);
this.Invoke(d, new object[] { text });
}
else
{
// Same thread, no Invoke.
this.txtLog.Text = this.txtLog.Text + text;
}
}
private void FinishSetText(string text)
{
this.txtLog.Text = this.txtLog.Text + text;
}
以上是修复我遇到的跨线程问题的错误代码。如果有更好的方法,我愿意尝试新事物。
// State object for receiving data from remote device.
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsyncClient
{
// The port number for the remote device.
private const int port = 8080;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
public struct properties
{
public static String response { get; set; }
}
public static Socket StartClient()
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
// Create a TCP/IP socket.
Socket client = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
return client;
}
catch (Exception e)
{
setText(e.ToString());
return client;
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
setText(string.Format("Socket connected to {0}",
client.RemoteEndPoint.ToString()));
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
setText(e.ToString());
}
//Other AsyncClient methods below.
}
在代码底部上方,您可以看到我尝试使用 Form1 中的方法设置文本的位置,但正如您还可以看到的那样,这些方法是静态的,这意味着它需要该方法的静态版本,这意味着使用This.textbox
不再起作用,或者至少这是我对正在发生的事情的理解。任何帮助将不胜感激。
删除 static
关键字并将此代码添加到 AsyncClient
class:
的开头
public class AsyncClient
{
private Action<string> setText;
public AsyncClient(Action<string> setText)
{
this.setText = setText;
}
然后,当您从表单创建实例时,只需执行 var ac = new AsyncClient(setText)
并调用 ac.StartClient()
。
所以我遇到的问题是我想在 Form1 上设置 textbox.Text。我很快发现线程安全,我认为我的代码解决了这个问题。我面临的下一个问题是我的客户编码的方式设置文本的方法必须是静态的,我不知道该怎么做。当然,除非我在 AsyncClient class 中的客户端方法不必是静态的,如果是这种情况,并且由于我缺乏知识,那就太好了。
正如您可能会说的那样,我正在为客户重新设计 Microsoft 的模板。这主要是因为我是一名大学生,目前只是用它来学习。
如果这个问题已经存在,我也想提前道歉,但是当我看的时候我找不到任何足够具体的问题来解决我的问题。
这是代码的顶部,去掉了命名空间。我会稍微拆分一下,只关注我谈到的部分。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket client;
public delegate void setTextCallback(string text);
public void setText(string text)
{
if (this.txtLog.InvokeRequired)
{
// Different thread, use Invoke.
setTextCallback d = new setTextCallback(FinishSetText);
this.Invoke(d, new object[] { text });
}
else
{
// Same thread, no Invoke.
this.txtLog.Text = this.txtLog.Text + text;
}
}
private void FinishSetText(string text)
{
this.txtLog.Text = this.txtLog.Text + text;
}
以上是修复我遇到的跨线程问题的错误代码。如果有更好的方法,我愿意尝试新事物。
// State object for receiving data from remote device.
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsyncClient
{
// The port number for the remote device.
private const int port = 8080;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
public struct properties
{
public static String response { get; set; }
}
public static Socket StartClient()
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
// Create a TCP/IP socket.
Socket client = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
return client;
}
catch (Exception e)
{
setText(e.ToString());
return client;
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
setText(string.Format("Socket connected to {0}",
client.RemoteEndPoint.ToString()));
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
setText(e.ToString());
}
//Other AsyncClient methods below.
}
在代码底部上方,您可以看到我尝试使用 Form1 中的方法设置文本的位置,但正如您还可以看到的那样,这些方法是静态的,这意味着它需要该方法的静态版本,这意味着使用This.textbox
不再起作用,或者至少这是我对正在发生的事情的理解。任何帮助将不胜感激。
删除 static
关键字并将此代码添加到 AsyncClient
class:
public class AsyncClient
{
private Action<string> setText;
public AsyncClient(Action<string> setText)
{
this.setText = setText;
}
然后,当您从表单创建实例时,只需执行 var ac = new AsyncClient(setText)
并调用 ac.StartClient()
。