private async void ButtonCalculate_Click(object sender, RoutedEventArgs e)
        {
            LabelStatus.Content = "calculating...";
            var watch = Stopwatch.StartNew();

            try
            {
                matr1      = matrixMultiplier.InitRandomMatrix(Matr1RowsAmount, Matr1ColsAmount);
                matr2      = matrixMultiplier.InitRandomMatrix(Matr2RowsAmount, Matr2ColsAmount);
                int[,] res = await matrixMultiplier.MultiplyAsync(matr1, matr2);

                //Debug.WriteLine("Matrix default method: ");
                //PrintMatrix(res);
            }
            catch (AggregateException ae)
            {
                MessageBox.Show("Wrong matrix sizes");
                LabelStatus.Content = "free";
                return;
            }

            watch.Stop();
            var elapsedMs = watch.ElapsedMilliseconds;

            LabelDefaultTime.Content = elapsedMs.ToString();

            try
            {
                watch = Stopwatch.StartNew();

                var matr1SplitList = MatrixMultiplier.Split2DArrayIntoRows(matr1, 3);
                var matr2SplitList = MatrixMultiplier.Split2DArrayIntoCols(matr2, 3);


                IEnumerable <Task <MatrixWithId> > multiplyMatrixTasksQuery = from m1 in matr1SplitList
                                                                              //join m2 in matr2SplitList on matr1SplitList.IndexOf(m1) equals matr2SplitList.IndexOf(m2)
                                                                              from m2 in matr2SplitList
                                                                              select matrixMultiplier.MultiplyAsync(m1, m2);

                Task <MatrixWithId>[] multiplyMatrixTasks = multiplyMatrixTasksQuery.ToArray();
                MatrixWithId[]        resultChunks        = await Task.WhenAll(multiplyMatrixTasks);

                resultChunks.OrderBy(x => x.id1).ThenBy(x => x.id2);
                int[,] res = new int[Matr1RowsAmount, Matr1ColsAmount];
                int currRowIndex = 0;
                int currColIndex = 0;
                int rowOffset    = 0;
                int colOffset    = 0;
                int currMatrId   = resultChunks[0].id1;

                for (int i = 0; i < resultChunks.Length; i++)
                {
                    if (currMatrId == resultChunks[i].id1)
                    {
                        currColIndex += colOffset;
                    }
                    else
                    {
                        currColIndex  = 0;
                        currRowIndex += rowOffset;
                    }

                    currMatrId = resultChunks[i].id1;

                    rowOffset = 0;
                    for (int j = 0; j < resultChunks[i].matr.GetLength(0); j++)
                    {
                        colOffset = 0;
                        for (int k = 0; k < resultChunks[i].matr.GetLength(1); k++)
                        {
                            res[j + currRowIndex, k + currColIndex] = resultChunks[i].matr[j, k];
                            colOffset++;
                        }
                        rowOffset++;
                    }
                }

                //Debug.WriteLine("Matrix async method: ");
                //PrintMatrix(res);

                watch.Stop();
                elapsedMs = watch.ElapsedMilliseconds;
                LabelAsyncTime.Content = elapsedMs.ToString();
            }
            catch (AggregateException ae)
            {
                Debug.WriteLine("*** ERROR *** " + ae.Message);
                return;
            }


            LabelStatus.Content = "free";
        }
 private void InitMatrixMultiplier()
 {
     matrixMultiplier = new MatrixMultiplier();
 }