//static readonly  Dictionary<Control, Thread> controls2sliding_thread = new Dictionary<Control, Thread>();

        public static Thread Condense(this Form f, double opacityPerMss, double opacity2, double step = 0.05, MethodInvoker finished = null)
        {
            lock (f)
            {
                Thread t = null;
                //if (controls2condensing_thread.TryGetValue(f, out t) && t.IsAlive)
                //    return t;

                step = f.Opacity < opacity2 ? step : -step;
                double total_mss = Math.Abs(opacity2 - f.Opacity) / opacityPerMss;
                int sleep = (int)(total_mss / ((opacity2 - f.Opacity) / step));
                t = ThreadRoutines.Start(() =>
                {
                    try
                    {
                        while (!(bool)ControlRoutines.Invoke(f, () =>
                            {
                                f.Opacity = f.Opacity + step;
                                return step > 0 ? f.Opacity >= opacity2 : f.Opacity <= opacity2;
                            })
                        )
                            System.Threading.Thread.Sleep(sleep);
                        ControlRoutines.Invoke(f, () =>
                        {
                            finished?.Invoke();
                        });
                    }
                    catch (Exception e)//control disposed
                    {
                    }
                });
                //controls2condensing_thread[f] = t;
                return t;
            }
        }
        public static Thread SlideVertically(this Control c, double pixelsPerMss, int position2, int step = 1, MethodInvoker finished = null)
        {
            lock (c)
            {
                Thread t = null;
                //if (controls2sliding_thread.TryGetValue(c, out t) && t.IsAlive)
                //    return t;

                step = c.Top > position2 ? -step : step;
                double total_mss = Math.Abs(position2 - c.Top) / pixelsPerMss;
                int sleep = (int)(total_mss / ((position2 - c.Top) / step));
                t = ThreadRoutines.Start(() =>
                {
                    try
                    {
                        while (c.Visible && !(bool)ControlRoutines.Invoke(c, () =>
                            {
                                c.Top = c.Top + step;
                                return step < 0 ? c.Top <= position2 : c.Top >= position2;
                            })
                        )
                            System.Threading.Thread.Sleep(sleep);
                        ControlRoutines.Invoke(c, () =>
                            {
                                finished?.Invoke();
                            });
                    }
                    catch(Exception e)//control disposed
                    {
                    }
                });
                //controls2sliding_thread[c] = t;
                return t;
            }
        }