Описание У меня есть пример кода для параллельного параллельного входа в систему. Требуется количество попыток входа в систему в Main
и передача его в ParallelRun
. ParallelRun
делит longinAttemptsCount
на количество потоков. Затем он порождает потоки и передает идентификатор потока и количество попыток на поток ThreadAuthenticationTaskRunner
AuthenticateAsync
выполняет фактический вход в систему.
ThreadAuthenticationTaskRunner
распечатывает, какой поток начиная с завершения, он выводит, какой поток закончился.
Ожидаемые результаты
Я ожидаю увидеть потоки, перечисленные в любом порядке, но я не буду видеть дублированные идентификаторы.
Фактические результаты
Я вижу, что некоторые идентификаторы потоков отсутствуют, а другие дублируются. Я получаю результаты, такие как:
Что это за ошибка параллелизма, которую я вижу здесь?
using System;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
namespace Stylelabs.M.WebSdk.Examples
{
public class Program
{
static void Main(string[] args)
{
int longinAttemptsCount = 1000;
Console.WriteLine("Main Thread Started");
//parallel run
ParallelRun(longinAttemptsCount);
Console.WriteLine("Main Thread Ended");
}
/// <summary>
/// Takes the number of required login attempts and spreads it across threads
/// </summary>
/// <param name="longinAttemptsCount"> Number of times to attempt to login</param>
static void ParallelRun(int longinAttemptsCount)
{
int numberOfLoginAttemptsPerThread = 100;
int numberOfThreads = longinAttemptsCount / numberOfLoginAttemptsPerThread;
Console.WriteLine("ParallelRun Started: " + numberOfThreads + " threads");
for (int i = 0; i < numberOfThreads; i++)
{
Thread thread1 = new Thread(() => ThreadAuthenticationTaskRunner(i, numberOfLoginAttemptsPerThread));
thread1.Start();
}
Console.WriteLine("ParallelRun Ended: " + numberOfThreads + " threads");
}
/// <summary>
/// Runs parallel logins for each thread
/// </summary>
/// <param name="threadId">The identifier of the running thread </param>
/// <param name="longinAttemptsCount">Number of times to attempt to login </param>
static async void ThreadAuthenticationTaskRunner(int threadId, int longinAttemptsCount)
{
Console.WriteLine("ThreadAuthenticationTaskRunner start for thread: " + threadId);
string userName = "administrator"; //user to log in
List<Task<String>> loginAttemptsResultsTasks = new List<Task<String>>();
//Executing the parallel logins
for (int i = 0; i < longinAttemptsCount; i++)
{
loginAttemptsResultsTasks.Add(AuthenticateAsync(userName, i, threadId));
}
var loginAttemptsResults = await Task.WhenAll(loginAttemptsResultsTasks);
foreach (string login in loginAttemptsResults)
{
Console.WriteLine(login);
}
Console.WriteLine("ThreadAuthenticationTaskRunner end for thread: " + threadId);
}
/// <summary>
/// Conducts an asynchronous login on a QA tenant
/// </summary>
/// <param name="userName"> The user to be logged in </param>
/// <param name="loginId"> The login attempt identifier </param>
/// <param name="threadId"> The identifier of the running thread </param>
/// <returns></returns>
static async Task<String> AuthenticateAsync(String userName, int loginId, int threadId)
{
String result;
try
{
//some asynchronous login logic here
result = "Success: loginId: " + loginId + " threadId: " + threadId;
}
catch (Exception e)
{
result = "Failure: loginId: " + loginId + " threadId: " + threadId + " error: " + e;
}
return result;
}
}
}