C# 并行。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)

出于负载测试的目的,我需要模拟多个用户试图同时登录到一个系统。我有另一个开发人员编写的代码,可以向系统发送登录请求。通过ok登录,它还将返回xml格式的其他信息

我尝试过使用Parallel.ForEach,但没有任何实际的并行编程经验:

   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: