// Three things to note in the signature:
        //  - The method has an async modifier.
        //  - The return type is Task or Task<T>. (See "Return Types" section.)
        //    Here, it is Task<int> because the return statement returns an integer.
        //  - The method name ends in "Async."
        async Task <StringBuilder> AccessTheWebAsync(CancellationToken token)
        {
            if (token.IsCancellationRequested)
            {
                return(new StringBuilder("cancelled"));
            }

            // You need to add a reference to System.Net.Http to declare client.
            var client = new HttpClient();

            // GetStringAsync returns a Task<string>. That means that when you await the
            // task you'll get a string (urlContents).
            var tsk = client.GetAsync("http://msdn.microsoft.com", token);

            // You can do work here that doesn't rely on the string from GetStringAsync.
            OutputResultControl.AppendText("Working . . . . . . ." + Environment.NewLine);

            if (token.IsCancellationRequested)
            {
                return(new StringBuilder("cancelled"));
            }

            // The await operator suspends AccessTheWebAsync.
            //  - AccessTheWebAsync can't continue until getStringTask is complete.
            //  - Meanwhile, control returns to the caller of AccessTheWebAsync.
            //  - Control resumes here when getStringTask is complete.
            //  - The await operator then retrieves the string result from getStringTask.
            var    response    = await tsk;
            string urlContents = await response.Content.ReadAsStringAsync();

            // The return statement specifies an integer result.
            // Any methods that are awaiting AccessTheWebAsync retrieve the length value.
            return(new StringBuilder(urlContents));
        }
        private async void SqrtLoad_Click(object sender, RoutedEventArgs e)
        {
            if (((Button)sender).Content.ToString() == "Cancel")
            {
                GetCanellationtokenForButton((Button)sender).Cancel();
                return;
            }

            var prev = ((Button)sender).Content;

            try
            {
                ((Button)sender).Content = "Cancel";

                int.TryParse(OutputResultControl.Text, out int count);

                var sum = await ComputeStuffAsync(count > 0?(int?)count : null,
                                                  GetCanellationtokenForButton((Button)sender).Token);

                OutputResultControl.AppendText($"Sqrt sum = {sum} {Environment.NewLine}");
            }
            catch (Exception ex)
            {
                //Show error
                OutputResultControl.Text = "Error: " + ex.Message;
            }
            finally
            {
                ((Button)sender).Content = prev;

                var cts = GetCanellationtokenForButton((Button)sender);
                if (cts.IsCancellationRequested)
                {
                    cts.Dispose();
                    _cancellationTokenSource.Remove(((Button)sender).Name);
                }
            }
        }
        async Task <StringBuilder> DoWorkAsync(SqlTester data, CancellationToken token)
        {
            if (token.IsCancellationRequested)
            {
                return(new StringBuilder("cancelled"));
            }

            var task = Task.Run(() =>
            {
                Dispatcher.Invoke(() =>
                {
                    OutputResultControl.AppendText("...working with...." + data.DataBaseType.ToString() + Environment.NewLine);
                });

                if (token.IsCancellationRequested)
                {
                    return(Task.FromResult(new StringBuilder("cancelled")));
                }

                return(data.Execute(token));
            });

            return(await task);
        }
        private async void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (((Button)sender).Content.ToString() == "Cancel")
            {
                GetCanellationtokenForButton((Button)sender).Cancel();
                return;
            }

            var prev = ((Button)sender).Content;

            try
            {
                OutputResultControl.Text = "starting multipple concurrency test" + Environment.NewLine;
                var db_type  = SelectedDBaseType;
                var tst_type = TestType;
                ((Button)sender).Content = "Cancel";
                int concurrentyCount = ConcurrencyCount.GetValueOrDefault(1);

                await Task.Factory.StartNew(() =>
                {
                    try
                    {
                        ParallelOptions po      = new ParallelOptions();
                        CancellationToken token = default;
                        Dispatcher.Invoke(() =>
                        {
                            token = GetCanellationtokenForButton((Button)sender).Token;
                            po.CancellationToken = token;
                        });
                        Parallel.For(0, concurrentyCount, po, async(i, pls) =>
                        {
                            try
                            {
                                var data = new SqlTester(db_type, tst_type);
                                Dispatcher.Invoke(() =>
                                {
                                    OutputResultControl.AppendText("starting test #" + i + " with " + data.DataBaseType.ToString() +
                                                                   Environment.NewLine);
                                });

                                var result = await data.Execute(token);

                                // Display the result. All is ok
                                Dispatcher.Invoke(() =>
                                {
                                    OutputResultControl.Text = result.ToString();
                                });
                            }
                            catch (OperationCanceledException)
                            {
                                pls.Stop();
                                Dispatcher.Invoke(() =>
                                {
                                    OutputResultControl.Text = "cancelled";
                                });
                                return;
                            }
                            catch (Exception ex)
                            {
                                //Show error
                                Dispatcher.Invoke(() =>
                                {
                                    OutputResultControl.Text = "Error: " + ex.Message;
                                });
                            }
                        });
                    }
                    catch (OperationCanceledException)
                    {
                        Dispatcher.Invoke(() =>
                        {
                            OutputResultControl.Text = "cancelled";
                        });
                    }
                    finally
                    {
                        //All sub-task ended. Notify UI
                        Dispatcher.Invoke(() =>
                        {
                            ((Button)sender).Content = prev;
                            var cts = GetCanellationtokenForButton((Button)sender);
                            if (cts.IsCancellationRequested)
                            {
                                cts.Dispose();
                                _cancellationTokenSource.Remove(((Button)sender).Name);
                            }
                        });
                    }
                });
            }
            catch (Exception ex)
            {
                //Show error
                OutputResultControl.Text = "Error: " + ex.Message;
            }
        }
        async Task <double> ComputeStuffAsync(int?inputCount, CancellationToken token)
        {
            var tsk = Task.Run(() =>
            {
                var sum = 0.0;
                int DOP = 4;
                //var count = inputCount ?? 16;
                var count       = inputCount ?? 4 * (100 * 1000 * 1000);
                long full_range = count / DOP;
                long reminder   = count % DOP + 1;

                if (full_range > 0)
                {
                    Parallel.For(0, DOP, new ParallelOptions {
                        MaxDegreeOfParallelism = DOP, CancellationToken = token
                    },
                                 // Initialize the local states
                                 () => 0.0,
                                 // Accumulate the thread-local computations in the loop body
                                 (th, loop, localState) =>
                    {
                        long from = full_range * (th);
                        long to   = full_range * (th + 1) - 1;

                        var computed = calc(from, to, loop);

                        //Dispatcher.Invoke(() =>
                        //{
                        //	OutputResultControl.AppendText($" th = {th}, from = {from}, to = {to}, computed = {computed} {Environment.NewLine}");
                        //});

                        return(localState + computed);
                    },
                                 // Combine all local states
                                 localState => Interlocked.Exchange(ref sum, sum + localState)
                                 );
                }
                if (reminder > 0)
                {
                    long from = full_range * DOP;
                    long to   = from + reminder - 1;

                    var computed = calcReminder(from, to);
                    sum         += computed;
                }

                return(sum);
            }, token);

            return(await tsk);

            //priv function
            double calc(long from, long to, ParallelLoopState loop)
            {
                double sum = 0;

                for (long i = from; i <= to && !loop.ShouldExitCurrentIteration; i++)
                {
                    sum += Math.Sqrt(i);
                    //sum += Approximate.Sqrt(i);
                    //sum += Approximate.Isqrt(i);
                }

                Dispatcher.Invoke(() =>
                {
                    OutputResultControl.AppendText($" from = {from}, to = {to}, sum = {sum} {Environment.NewLine}");
                });

                return(sum);
            }

            double calcReminder(long from, long to)
            {
                double sum = 0;

                for (long i = from; i <= to && !token.IsCancellationRequested; i++)
                {
                    sum += Math.Sqrt(i);
                    //sum += Approximate.Sqrt(i);
                    //sum += Approximate.Isqrt(i);
                }

                Dispatcher.Invoke(() =>
                {
                    OutputResultControl.AppendText($" from = {from}, to = {to}, sum = {sum} {Environment.NewLine}");
                });

                return(sum);
            }
        }