C# 多线程:在线程之间传递不同的自定义控件属性(或异步使用它们)
我正在尝试开发一个项目,在这个项目中,我可以让多个客户机发出他们自己的服务器请求,以便进行压力测试。当我创建一个新线程并希望该线程完成工作时,我很难弄清楚如何操作自定义控件属性。我有超过100个控件;理想情况下,100名个人客户。问题是我的控件是GUI的一部分,我不知道如何允许有问题的线程从相对控件访问 以下是我所拥有的:C# 多线程:在线程之间传递不同的自定义控件属性(或异步使用它们),c#,winforms,C#,Winforms,我正在尝试开发一个项目,在这个项目中,我可以让多个客户机发出他们自己的服务器请求,以便进行压力测试。当我创建一个新线程并希望该线程完成工作时,我很难弄清楚如何操作自定义控件属性。我有超过100个控件;理想情况下,100名个人客户。问题是我的控件是GUI的一部分,我不知道如何允许有问题的线程从相对控件访问 以下是我所拥有的: // Custom project.class to get access to a custom base of properties created within
// Custom project.class to get access to a custom base of properties created within the tool itself.
List<custom_control_project.custom_control_widget> controlList = new List<custom_control_project.custom_control_widget>();
private async void btnStart_Click(object sender, EventArgs e)
{
...// control property initializations
foreach (var control in controlList)
{
if (control.Enabled)
{
Thread thread = new Thread(() => StartClient());
thread.Start();
// Loop until worker thread activates.
while (!thread.IsAlive);
... // Ideally the GUI updates would happen from these threads. Simple updates to labels based on status code responses and expected xml parameters received.
}
}
如何从传入方法的foreach语句中获得相对控制,然后根据结果修改GUI(以某种方式调用?)?此外,是否有可能使每个客户机独立,并同时具有多个客户机到服务器到客户机的请求?这是我的主要目标
如果这是一种牵强的或非常令人沮丧的尝试方式,请这样说。如果不钻研太多编程术语(为了理解目的,我对编程相当陌生),您将如何着手进行这项工作
提前谢谢 那么,您可以通过使用控件上的BeginInvoke
函数,传递要执行的操作,从不同的线程对任何控件进行排序操作。该操作将在UI线程上执行
但你的主要问题是你没能做到。您的UI代码可以确保操作发生,但这些操作应该与任何UI代码不同。您应该以这样一种方式来设计您的操作,使其可重用。换句话说,如果您决定从头开始重写UI,您应该仍然能够按原样重用您的操作
为了实现这一点,您的操作不应该引用任何UI,甚至不应该知道任何UI的存在。这将使您的代码更易于管理。因此,在不同的类中提取所有这些内容,然后使用事件之类的东西与UI进行通信。然后,用户界面代码将进行
BeginInvoke
呼叫。感谢您的回复。我将研究为此使用事件。我同意现在我的代码没有正确地分开。我想您的意思是,不需要来回传递相关的控件属性,只需在一个方法中完成所有处理并调用主GUI。我不知道如何在这个上下文中连接事件,但我会学习。你应该将数据封装到有意义的类中,并传递这些类,而不是传递UI控件。
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
// ManualResetEvent instances signal completion.
private ManualResetEvent connectDone =
new ManualResetEvent(false);
private ManualResetEvent sendDone =
new ManualResetEvent(false);
private ManualResetEvent receiveDone =
new ManualResetEvent(false);
// The response from the remote device.
private String response = String.Empty;
public void StartClient()
{
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// The name of the
// remote device is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve("host.contoso.com");
//IPAddress ipAddress = ipHostInfo.AddressList[0];
//IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect(asyncServerHolder, asyncPortHolder,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send test data to the remote device.
Send(client, (Upload)); //POST HTTP string + xml parameters
sendDone.WaitOne();
// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();
// Write the response to the console.
//MessageBox.Show("Response received : " + response);
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
// Reset all manual events for next instance.
connectDone.Reset();
sendDone.Reset();
receiveDone.Reset();
}
catch (Exception)
{
//MessageBox.Show(e.ToString());
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
//MessageBox.Show("Socket connected to " + client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception)
{
//MessageBox.Show(e.ToString());
}
}
private void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception)
{
//MessageBox.Show(e.ToString());
}
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response1 = state.sb.ToString();
///
///
/// **THIS IS WHERE I WANT ALL THE PROCESSING TO BE DONE**
/// **AFTER THE RESPONSE IS COMPLETE!!**
///
///
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception)
{
//MessageBox.Show(e.ToString());
}
}
private void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
//MessageBox.Show("Sent " + bytesSent + " bytes to server.");
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception)
{
//MessageBox.Show(e.ToString());
}
}