Esempio n. 1
0
        public ApplicationWindow()
        {
            InitializeComponent();

            _DamageDispalyListState = DamageDispalyListState.Waiting;

            _BackgroundRunnerTask = _BackgroundRunner(_BackgroundRunnerTokenSource.Token).ContinueWith((t) =>
            {
                if (t.IsFaulted)
                {
                    ExceptionDispatchInfo.Capture(t.Exception.InnerException).Throw();
                }
            });
        }
Esempio n. 2
0
        private async Task _BackgroundRunner(CancellationToken ct)
        {
            _Accumulator.InfosChanged += (sender, infos) =>
            {
                var ordered = infos.OrderByDescending(x => x.TotalDamage);
                var items   = ordered.Select(i => new DamageDisplayList.DamageDisplayData
                {
                    Name              = i.Name,
                    Damage            = i.TotalDamage,
                    DamageRatio       = (100.0 / ordered.First().TotalDamage) * i.TotalDamage,
                    DamageRatioNormal = (100.0 / ordered.First().TotalDamage) * i.TotalDamage,
                    MaxHitDamage      = i.MaxHitDamage,
                    MaxHitName        = $"Id: {i.MaxHitAction}"
                });

                Dispatcher.Invoke(() =>
                {
                    _DamageDisplayList.Items.Clear();
                    foreach (var i in items)
                    {
                        _DamageDisplayList.Items.Add(i);
                    }
                    _DamageDispalyListState = DamageDispalyListState.Visible;
                });
            };

            // TODO: this should probably be done in a better way.
            // at the moment if anything goes wrong the system will
            // reset the accumulator and start again, ~better than a crash?~
            while (true)
            {
                ct.ThrowIfCancellationRequested();

                // wait for file to show up
                var logFile = _GetLatestLogFile(_DamageDumpFolder);
                if (logFile == null)
                {
                    await Task.Delay(1000, ct);

                    continue;
                }

                try
                {
                    Dispatcher.Invoke(() => _DamageDispalyListState = DamageDispalyListState.Loading);

                    var watcher = new LogFileWatcher();
                    watcher.OnNewEntries += async(sender, entries) =>
                    {
                        await _BackgroundSemaphore.WaitAsync();

                        try
                        {
                            _Accumulator.ProcessEntries(entries);
                        }
                        finally
                        {
                            _BackgroundSemaphore.Release();
                        }
                    };

                    using (var fsWatcher = new FileSystemWatcher())
                    {
                        fsWatcher.Path = _DamageDumpFolder;

                        var fsWatcherSource = new CancellationTokenSource();
                        void OnFsChanged(object source, object _)
                        {
                            if (_GetLatestLogFile(_DamageDumpFolder) != logFile)
                            {
                                fsWatcherSource.Cancel();
                            }
                        }

                        fsWatcher.Created += OnFsChanged;
                        fsWatcher.Deleted += OnFsChanged;
                        fsWatcher.Changed += OnFsChanged;
                        fsWatcher.Renamed += OnFsChanged;

                        fsWatcher.EnableRaisingEvents = true;

                        await watcher.RunAsync(logFile, CancellationTokenSource.CreateLinkedTokenSource(ct, fsWatcherSource.Token).Token);
                    }
                }
                catch (OperationCanceledException)
                {
                    // this exception does not mean anything as there are multiple
                    // cancellation tokens that could have caused it, the function however
                    // only cancels to one specific token and that is handled separately
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"Exception in log file watcher loop -> {ex.Message}");
                }
                finally
                {
                    await _ResetAccumulator();

                    Dispatcher.Invoke(() => _DamageDispalyListState = DamageDispalyListState.Waiting);
                }
            }
        }