Список возвращает одно и то же значение в поток каждый раз, даже если в списке нет дубликатов - PullRequest
0 голосов
/ 31 октября 2019

Итак, я написал программу, которая выполняет HTTP API-вызовы к сервису, который мы используем на работе. Я пытался оптимизировать его с помощью Threadpool, и я вполне доволен результатом (по времени). Однако, как вы можете видеть ниже, call-url уникален для каждого вызова, потому что в конце он имеет идентификатор, который выбирается из списка. Значения списка считываются из локального файла, который не содержит дубликатов и в указанном списке нет дубликатов. Я знаю это, потому что я старался изо всех сил в отладке и видел, что все элементы уникальны. Я буквально понятия не имею, почему и мог бы действительно использовать некоторые разъяснения по этому вопросу. Кроме того, кажется, что значение, которое возвращается каждый раз, является последним элементом списка, каждый раз.

=> Попытался сделать пошаговый переход в VS, чтобы увидеть, было ли где-то, я использовал числа [0] вместоиз чисел [я], но ни один не найден. Хотя, когда я перешагнул через код вручную, я увидел, что возвращаемые значения не совпадают, но я не знаю почему?

=> Попытка сделать список глобальной переменной и заблокировать его, но в результате получаетсявсе то же самое, то же самое значение отправляется каждый раз.

//new code
object changeObjectsLock = new object();
List<Change> changeObjects = new List<Change>();

object amountOfCallsMade = new object();
int callCount = 0;

Parallel.For(0, changeIds.Count, index =>
{
    try
    {
        string receivedJson;
        httpWebRequest = (HttpWebRequest)WebRequest.Create(myApiUrl);
        httpWebRequest.Headers["Auth"] = "token";
        httpResponse = (HttpWebResponse)httpWebRequest.Getresponse();

        using (StreamReader reader = new StreamReader(httpResponse.GetResponseStream()))
        {
            receivedJson = reader.ReadToEnd();

            lock (changeObjectsLock)
            {
                changeObjects.Add(JsonConvert.Deserialize<Change>(receivedJson, jsonSettings));
            }
        }

        lock (amountOfCallsMade)
        {
            ++callCount;
            Console.WriteLine($"Call No: {callCount}\tID: {changeIds[index]}");
        }
    }
    catch (Exception) { }
});

//Old code

private static object changeObjectsLock = new object();
private static List<Change> changeObjects = new List<Change>();

private static object activeWorkersLock = new object();
private static int countOfActiveWorkers = 0;

private static object amountOfCallsMade = new object();
private static int callCount = 0;

private static object changeIdLock = new object();
private static List<string> changeIds = new List<string>();

static void Main(string[] args)
{
    changeIds = GetChangeNumbers(); //changeIds is now populated
    Action<object> getRequestAction = DoGetRequest;
    GetAllRequests(getRequestAction, new object[] { null, httpWebRequest, httpResponse, token, jsonSettings });
}

private static void GetAllRequests(Action<object> action, object state)
{
    object[] stateArr = state as object[];

    do
    {
        lock (changeIdLock)
        {
            stateArr[0] = changeIds[0]
            changeIds.RemoveAt(0);
        }
        object[] actionData = stateArr;
        Action wrappedAction = () => { action(actionData); };

        lock (activeWorkersLock)
        {
            ++countOfActiveWorkers;
        }

        ThreadPool.QueueUserWorkItem(x => wrappedAction());

    } while (changeIds.Count != 0)

    lock (activeWorkersLock)
    {
        while (countOfActiveWorkers > 0)
        {
            Monitor.Wait(activeWorkersLock);
        }
    }
}

private static void DoGetRequest(object state)
{
    try
    {
        object[] array = state as object[];
        string number = array[0] as string;
        HttpWebRequest httpWebRequest = array[1] as HttpWebRequest;
        HttpWebResponse httpResponse = array[2] as HttpWebResponse;
        string token = array[3] as string;
        JsonSerializerSettings jsonSettings = array[4] array[4] as JsonSerializerSettings;
        string receivedJson;

        httpWebRequest = (HttpWebRequest)WebRequest.Create($"https://myapi.com/api/getInfo/{number}");
        httpWebRequest.Headers["Auth"] = token;
        httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();

        using (StreamReader reader = new StreamReader(httpResponse.GetResponseStream()))
        {
            receivedJson = reader.ReadToEnd();

            lock (changeObjectsLock)
            {
                changeObjects.Add(JsonConvert.DeserializeObject<Change>(receivedJson, jsonSettings));
            }
        }
        Console.WriteLine($"Current ID: {number}");
    }
    catch (Exception) { }
    finally
    {
        lock (activeWorkersLock)
        {
            --countOfActiveWorkers;
            Monitor.PulseAll(activeWorkersLock)
        }

        lock (amountOfCallsMade)
        {
            ++callCount;
            Monitor.PulseAll(amountOfCallsMade);
        }
    }
}

Желаемый вывод / результат состоит в том, что все вызовы должны быть на уникальных идентификаторах. Если вы посмотрите на строку записи, которая выдает «Текущий идентификатор: номер», она будет выводить одно и то же число каждый раз, независимо от того, что я пытаюсь сделать. Я хочу, чтобы каждый номер был уникальным.

...