C# 并行。Foreach不完成流
出于负载测试的目的,我需要模拟多个用户试图同时登录到一个系统。我有另一个开发人员编写的代码,可以向系统发送登录请求。通过ok登录,它还将返回xml格式的其他信息 我尝试过使用Parallel.ForEach,但没有任何实际的并行编程经验:C# 并行。Foreach不完成流,c#,.net,task-parallel-library,C#,.net,Task Parallel Library,出于负载测试的目的,我需要模拟多个用户试图同时登录到一个系统。我有另一个开发人员编写的代码,可以向系统发送登录请求。通过ok登录,它还将返回xml格式的其他信息 我尝试过使用Parallel.ForEach,但没有任何实际的并行编程经验: Parallel.ForEach(clientList, client => { RunTest(client); }); public void RunTest(object data)
Parallel.ForEach(clientList, client =>
{
RunTest(client);
});
public void RunTest(object data)
{
if (!(data is IGprsClient))
{
return;
}
_noRunningTests += 1;
IGprsClient gprsClient = data as IGprsClient;
DateTime startTime = DateTime.Now;
Log(gprsClient.Id, "Test started.");
bool result = gprsClient.StartTest(20000);
DateTime endTime = DateTime.Now;
TimeSpan diff = endTime - startTime;
if (result == false)
{
Log(gprsClient.Id, "Test failed.");
}
Log(gprsClient.Id, "Test took {0}ms. ", (int)diff.TotalMilliseconds);
_noRunningTests -= 1;
}
override public bool StartTest(int timeout)
{
_testStarted = true;
try
{
LogDebug("Trying to connect.");
_client = new TcpClient(ipAddress, port);
LogDebug("Connected.");
bool result = false;
//Todo: insert testcase into client
switch (TestCaseName)
{
case "LoginTEST":
var testCase = new LoginTEST(this);
result = testCase.Execute(user, pwd, phoneNum);
break;
default:
Log("Unknown test case: " + TestCaseName);
break;
}
_client.Close();
return result;
}
catch (Exception ex)
{
if (_client != null)
_client.Close();
Log(ex.Message);
return false;
}
}
然后发送请求并读取响应
public bool Execute(string user, string pwd, string phoneNum)
{
SendDataListRequest(userId);
string requiredDataResponse = Client.ReadMsg();
return true;
}
运行测试将发送一个请求,并按如下方式读取消息:
public string ReadMsg()
{
int msgLength = -1;
var stream = _client.GetStream();
while (_testStarted)
{
int b = stream.ReadByte();
if (b == -1)
{
return "";
}
else if (b == 0x02 || msgLength == -1)
{
while (b != 0x02 && _testStarted)
{
b = stream.ReadByte(); // Finds the start token
if (b == -1)
{
return "";
}
}
msgLength = 0; // Starts collecting data
}
else if (b == 0x03)
{
byte[] encryptedMsg = Convert.FromBase64String(
Encoding.UTF8.GetString(byteBuffer, 0, msgLength));
byte[] decryptedMsg = SttCipher.DecryptMessage(encryptedMsg);
MemoryStream ms = new MemoryStream(decryptedMsg);
GZipStream gZipStream = new GZipStream(ms, CompressionMode.Decompress, true);
var bufLen = ReadAllBytesFromStream(gZipStream, decompressedBuffer);
gZipStream.Close();
string completeMsg = Encoding.UTF8.GetString(decompressedBuffer, 0, bufLen);
if (completeMsg.Length < 500)
LogDebug("Received XML-data:\n{0}", completeMsg);
else
LogDebug("Received XML-data: {0} bytes\n{1}...", completeMsg.Length, completeMsg.Substring(0, 500));
return completeMsg;
}
else
{
if (byteBuffer.Length <= msgLength)
{
throw new Exception("XML message too long!");
}
byteBuffer[msgLength] = (byte)b;
msgLength++;
}
}
return "";
}
公共字符串ReadMsg()
{
int msgLength=-1;
var stream=_client.GetStream();
while(_teststart)
{
int b=stream.ReadByte();
如果(b==-1)
{
返回“”;
}
else if(b==0x02 | | msgLength==1)
{
而(b!=0x02&&u测试已启动)
{
b=stream.ReadByte();//查找开始标记
如果(b==-1)
{
返回“”;
}
}
msgLength=0;//开始收集数据
}
else if(b==0x03)
{
字节[]encryptedMsg=Convert.FromBase64String(
Encoding.UTF8.GetString(byteBuffer,0,msgLength));
字节[]decryptedMsg=SttCipher.DecryptMessage(encryptedMsg);
MemoryStream ms=新的MemoryStream(decryptedMsg);
GZipStream GZipStream=新的GZipStream(ms,CompressionMode.decompresse,true);
var bufLen=ReadAllBytesFromStream(gZipStream,decompressedBuffer);
gZipStream.Close();
string completeMsg=Encoding.UTF8.GetString(decompressedBuffer,0,bufLen);
如果(完整长度<500)
LogDebug(“接收到的XML数据:\n{0}”,completeMsg);
其他的
LogDebug(“收到的XML数据:{0}字节\n{1}…”,completeMsg.Length,completeMsg.Substring(0500));
返回completeMsg;
}
其他的
{
如果(byteBuffer.Length什么是_testStarted?何时设置为false?我的猜测是,当您的代码运行时,此参数设置为false,并且您得到的xml不完整。检查共享状态。如果您有每个并行循环之间共享的状态,则可能会遇到问题。@Ehsan _testStarted在测试启动时设置为true。我我添加了一些代码来反映这一点。@simon我看不出它们之间有任何共享状态。可能是读取流时使用的某些方法是非线程安全的吗?例如,不支持读取Filestream.Writebyte: