Пример #1
0
        private unsafe void OnRunButtonClick(object sender, EventArgs e)
        {
            if (!EstimateTime(false))
            {
                return;
            }

            double start, end;

            double.TryParse(startTextBox.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out start);
            double.TryParse(endTextBox.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out end);

            if (estimatedTime.TotalMinutes > 0.5)
            {
                string timeString;
                if (estimatedTime == TimeSpan.MaxValue)
                {
                    timeString = Tx.T("time.infinitely");
                }
                else
                {
                    timeString = estimatedTime.ToTextString();
                }

                if (MessageBox.Show(this, Tx.T("find diffs.errors.interval too big", Tx.N(distance), timeString), Tx.T("main.warning"),
                                    MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
                {
                    return;
                }
            }

            long starti = *(long *)&start;
            long endi   = *(long *)&end;

            if (starti > endi)
            {
                long swap = starti;
                starti = endi;
                endi   = swap;
            }
            distance = (endi - starti);

            long currentProcessed = 0, lastProcessed = 0;
            long differencesFound = 0;

            SpinLock syncLock = new SpinLock();

            ProgressDialog progressDialog = new ProgressDialog {
                Text            = Tx.T("find diffs.finding.title"),
                MainInstruction = Tx.T("find diffs.finding.description"),
                Line1           = Tx.T("find diffs.finding.progress", "0", Tx.N(distance)),
                ShowInTaskbar   = false,
                MinimizeBox     = false
            };

            ThreadPool.UnsafeQueueUserWorkItem(delegate {
                BeginInvoke((MethodInvoker) delegate {
                    progressDialog.ShowDialog(this);
                });

                Stopwatch sw = Stopwatch.StartNew();

                Parallel.For(starti, endi, (xi, state) => {
                    double x = *(double *)ξ

                    bool isFirst        = true;
                    double computedMinY = double.MaxValue, computedMaxY = double.MinValue;

                    foreach (ListView.Item item in listView.Items)
                    {
                        if (item.NumericValueSource == null || item.CheckState != CheckState.Checked)
                        {
                            continue;
                        }

                        double y = item.NumericValueSource.Evaluate(x);

                        if (isFirst)
                        {
                            isFirst      = false;
                            computedMinY = y;
                            computedMaxY = y;
                        }
                        else
                        {
                            if (y > computedMaxY)
                            {
                                computedMaxY = y;
                            }
                            else if (y < computedMinY)
                            {
                                computedMinY = y;
                            }
                        }
                    }

                    bool lockTaken = false;
                    syncLock.Enter(ref lockTaken);

                    if (!isFirst && computedMinY != computedMaxY)
                    {
                        graph.AddDifferenceUnsafe(x, computedMinY, computedMaxY);
                        differencesFound++;
                    }

                    if (sw.ElapsedMilliseconds > 4000)
                    {
                        if (progressDialog.IsCancelled)
                        {
                            if (lockTaken)
                            {
                                syncLock.Exit();
                            }
                            state.Stop();
                            return;
                        }

                        sw.Stop();

                        long delta         = (currentProcessed - lastProcessed);
                        long rate          = delta * 1000 / (long)sw.Elapsed.TotalMilliseconds;
                        TimeSpan remaining = TimeSpan.FromSeconds((distance - currentProcessed) / rate);

                        lastProcessed = currentProcessed;

                        BeginInvoke((MethodInvoker) delegate {
                            progressDialog.Line1    = Tx.T("find diffs.finding.progress", Tx.N(lastProcessed), Tx.N(distance));
                            progressDialog.Line2    = Tx.T("main.remaining time", remaining.ToTextString());
                            progressDialog.Progress = (int)(lastProcessed * 100 / distance);
                        });

                        sw.Restart();
                    }

                    currentProcessed++;

                    if (lockTaken)
                    {
                        syncLock.Exit();
                    }
                });

                sw.Stop();

                BeginInvoke((MethodInvoker) delegate {
                    progressDialog.TaskCompleted();

                    if (!progressDialog.IsCancelled)
                    {
                        MessageBox.Show(this,
                                        Tx.T("find diffs.complete.description",
                                             Tx.N(distance),
                                             Tx.N(differencesFound),
                                             Tx.N(differencesFound * 100 / distance)),
                                        Tx.T("find diffs.complete.title"),
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                });
            }, null);
        }