internal static async Task <(bool started, string failReason)> StartDeviceTask(ComputeDevice device) { device.StartState = true; // we can only start a device it is already stopped if (device.State == DeviceState.Disabled) { return(false, "Device is disabled"); } if (device.State != DeviceState.Stopped && device.State != DeviceState.Error) { return(false, "Device already started"); } var started = true; var failReason = ""; var allAlgorithmsDisabled = !device.AnyAlgorithmEnabled(); var isAllZeroPayingState = device.AllEnabledAlgorithmsZeroPaying(); // check if device has any benchmakrs var needBenchmarkOrRebench = device.AnyEnabledAlgorithmsNeedBenchmarking(); if (allAlgorithmsDisabled) { device.State = DeviceState.Error; started = false; failReason = "Cannot start a device with all disabled algoirhtms"; } else if (isAllZeroPayingState && !needBenchmarkOrRebench) { device.State = DeviceState.Error; started = false; failReason = "No enabled algorithm is profitable"; } else { await MiningManager.StartDevice(device); } return(started, failReason); }
private async Task Benchmark() { bool showFailed = false; bool startMining = false; _stopBenchmark = CancellationTokenSource.CreateLinkedTokenSource(ApplicationStateManager.ExitApplication.Token); try { foreach (var a in _algorithms) { a.SetBenchmarkPending(); } var benchAlgos = new Queue <AlgorithmContainer>(_algorithms); //BenchmarkingHandlers.TryAdd(Device, this); // whole benchmark scope var commandTask = GetCommand(_stopBenchmark.Token); // Until container is not empty while (benchAlgos.Any() && !_stopBenchmark.IsCancellationRequested) { // per algo benchmark scope bool?benchmarkSuccess = null; _stopCurrentAlgorithmBenchmark = CancellationTokenSource.CreateLinkedTokenSource(_stopBenchmark.Token); try { var nextAlgo = benchAlgos.Dequeue(); var benchmark = BenchmarkAlgorithm(nextAlgo, _stopCurrentAlgorithmBenchmark.Token); var firstFinished = await Task.WhenAny(new Task <object>[] { commandTask, benchmark }); var ret = await firstFinished; if (ret is IReadOnlyList <AlgorithmContainer> updatedAlgorithms) { commandTask = GetCommand(_stopBenchmark.Token); var stop = _algorithms.Except(updatedAlgorithms).Any(algo => algo == nextAlgo); var restAlgorithms = updatedAlgorithms.Where(algo => algo != nextAlgo).ToArray(); // update Algorithms _algorithms = restAlgorithms; foreach (var a in _algorithms) { a.SetBenchmarkPending(); } // updated benchAlgos = new Queue <AlgorithmContainer>(_algorithms); if (stop) { // THIS Throws _stopCurrentAlgorithmBenchmark.Cancel(); } else { // wait for the current benchmark to finish ret = await benchmark; } } if (ret is bool success) { benchmarkSuccess = success; } // this will drain the container await Task.Delay(MiningSettings.Instance.MinerRestartDelayMS, _stopCurrentAlgorithmBenchmark.Token); } catch (TaskCanceledException e) { Logger.Debug("BenchmarkingDevice", $"TaskCanceledException occurred in benchmark task: {e.Message}"); } catch (Exception e) { Logger.Error("BenchmarkingDevice", $"Exception occurred in benchmark task: {e.Message}"); } finally { _stopCurrentAlgorithmBenchmark.Dispose(); if (!_stopCurrentAlgorithmBenchmark.IsCancellationRequested && benchmarkSuccess.HasValue && !benchmarkSuccess.Value) { showFailed = true; } } } startMining = !_stopBenchmark.IsCancellationRequested; // clear what we didn't benchmark while (benchAlgos.Any()) { var nextAlgo = benchAlgos.Dequeue(); nextAlgo.ClearBenchmarkPending(); } if (showFailed) { AvailableNotifications.CreateFailedBenchmarksInfo(Device); } } catch (Exception ex) { Logger.Error("BenchmarkingDevice2", $"Exception occurred in benchmark task: {ex.Message}"); } finally { _stopBenchmark.Dispose(); if (startMining) { _ = MiningManager.StartDevice(Device); // important do not await } else { Device.State = DeviceState.Stopped; } } }