/// <summary> /// Fetches prime numbers from existing result files. /// </summary> /// <param name="fileHandler">The object handling the result files.</param> /// <returns>Container holding information about the loaded prime numbers.</returns> public ExistingPrimesLoadingResult FetchExistingPrimes(ResultFileHandler fileHandler) { //Tell the user the loading has started. var startingArgs = new LoadingPrimesFromResultFileStartedArgs(); OnLoadingPrimesFromResultFileStarted?.Invoke(this, startingArgs); //Load the existing primes. var result = fetchPrimes(fileHandler.ResultFiles); //Store the index of the last result file with room for more prime numbers. result.IndexOfLastResultFileToStoreIn = findFirstStorableFileIndex(fileHandler.ResultFiles); //Tell the user that the loading finished. int numberOfPrimesLoaded = result.CachedPrimes.Count; int numberOfResultFilesLoaded = (int)Math.Ceiling(result.CachedPrimes.Count / (decimal)Configuration.NumberOfPrimesInFile); var loadingFinishedArgs = new LoadingPrimesFromResultFileFinishedArgs(numberOfPrimesLoaded, numberOfResultFilesLoaded); OnLoadingPrimesFromResultFileFinished?.Invoke(this, loadingFinishedArgs); //Return the result from the loading. return(result); }
/// <summary> /// Starts the prime number generation. /// </summary> public void GeneratePrimes() { //Set the handler handling the result files. FileHandler = new ResultFileHandler(); FileHandler.OnPrimesWrittenToFile += FileHandler_OnPrimesWrittenToFile; //Load existing primes. var loader = new ExistingPrimesLoader(); loader.OnLoadingPrimesFromResultFileStarted += Loader_OnLoadingPrimesFromResultFileStarted; loader.OnLoadingPrimesFromResultFileFinished += Loader_OnLoadingPrimesFromResultFileFinished; loader.OnLoadingPrimesFromFile += Loader_OnLoadingPrimesFromFile; var loadResult = loader.FetchExistingPrimes(FileHandler); //End the execution if the user aborted it. if (loadResult.ExecutionWasAborted) { return; } //Extract the data from the loading result. CachedPrimes = loadResult.CachedPrimes; MemoryLimitReached = loadResult.MemoryLimitReached; var numberToCheck = loadResult.NextNumberToCheck; //Setup variables for prime number generation. bool isPrime = false; try { //Inform the subscriber that the prime number generation has started. OnPrimeGenerationStarted?.Invoke(this, new PrimeGenerationStartedArgs()); FileHandler.PrimeNumberGenerationHasStarted(); //Skip memory stored generation if the memory was filled by the already generated prime numbers. if (!MemoryLimitReached) { //Create variable keeping track of were the unstored primes begin. var indexOfFirstUnstoredPrime = CachedPrimes.Count; //Generate the first primes quickly by using only the computer memory. Func <bool> memoryIteration = delegate() { //Check if the number is a prime. isPrime = PrimeChecker.IsPrimeNumber(CachedPrimes, numberToCheck); //Handle prime find. if (isPrime) { try { //Add the prime to the list. CachedPrimes.Add(numberToCheck); } catch (OutOfMemoryException ex) { if (Tools.MemoryIsFilledWithPrimes(ex)) { //We have reached the limit for how many primes the computer memory can hold. MemoryLimitReached = true; //Stop using the computer memory when generating prime numbers. return(false); } else { //Unknown error. Keep throwing. throw; } } //Write the primes to a file for reading by the user. if (CachedPrimes.Count % Configuration.NumberOfPrimesInFile == 0) { writePrimesToFile(CachedPrimes, indexOfFirstUnstoredPrime, Configuration.NumberOfPrimesInFile); indexOfFirstUnstoredPrime = CachedPrimes.Count; } } //Prepare checking the next number. numberToCheck++; //Keep generating prime numbers. return(true); }; runInfiniteLoopUntilEscapeIsPressed(memoryIteration); //Unless the memory limit is reached, it was the user who stopped the generation. if (!MemoryLimitReached) { return; } //Store the unstored primes. storeUnsavedPrimesAfterMemoryOverflow(CachedPrimes, numberToCheck); } //Generate the rest of the primes by using the harddrive as memory. Func <bool> diskIteration = delegate() { throw new NotImplementedException(); }; runInfiniteLoopUntilEscapeIsPressed(diskIteration); } catch (Exception ex) { ex.Data.Add("CurrentNumberToCheck", numberToCheck); //Rethrow the exception. throw; } }