Waiting Processed Cancelable ShowDialog (Release 2)


namespace Test
{
    using System;
    using System.Windows.Forms;
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}
namespace Test
{
    using System;
    using System.Threading;
    using System.Windows.Forms;
    using Microshaoft;
    partial class MainForm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(119, 74);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // MainForm
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(282, 253);
            this.Controls.Add(this.button1);
            this.Name = "MainForm";
            this.Text = "MainForm";
            this.ResumeLayout(false);
        }
        #endregion
        private System.Windows.Forms.Button button1;
    }
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            var r = TaskProcesserHelper.ProcessWaitingShowDialog40
                                    (
                                        this
                                        , new ProcessWaitingCancelableDialog()
                                        , () =>
                                        {
                                            Thread.Sleep(5 * 1000);
                                            //throw new Exception();
                                        }
                                        , () =>
                                        {
                                            Console.WriteLine("Finished");
                                        }
                                        , (x) =>
                                        {
                                            Console.WriteLine("Caught Exception: {0}", x);
                                        }
                                    );
            Console.WriteLine(r);
        }
    }
}
namespace Microshaoft
{
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    public static class TaskProcesserHelper
    {
        public static int ProcessWaitingShowDialog
                    (
                        IWin32Window ownerWindow
                        , Func<Form> onWaitingDialogFactoryFunc
                        , Action onProcessAction = null
                        , Action onProcessedAction = null
                        , Action<Exception> onCaughtExceptionProcessAction = null
                    )
        {
            var dialogForm = onWaitingDialogFactoryFunc();
            return
                ProcessWaitingShowDialog
                            (
                                ownerWindow
                                , dialogForm
                                , onProcessAction = null
                                , onProcessedAction = null
                                , onCaughtExceptionProcessAction = null
                            );
        }
        public static int ProcessWaitingShowDialog40
                            (
                                IWin32Window ownerWindow
                                , Form dialogForm
                                , Action onProcessAction = null
                                , Action onProcessedAction = null
                                , Action<Exception> onCaughtExceptionProcessAction = null
                            )
        {
            var r = 1;
            Task<DialogResult> task1 = Task.Factory.StartNew<DialogResult>
                            (
                                () => 
                                {
                                    return dialogForm.ShowDialog();
                                }
                            );
            Task task2 = Task.Factory.StartNew
                                    (
                                        () =>
                                            {
                                                try
                                                {
                                                    //
                                                    onProcessAction();
                                                    r = 0;
                                                }
                                                catch (Exception e)
                                                {
                                                    r = -1;
                                                    if (onCaughtExceptionProcessAction != null)
                                                    {
                                                        onCaughtExceptionProcessAction(e);
                                                    }
                                                }
                                                finally
                                                {
                                                    TrySafeInvokeFormClose
                                                        (
                                                            dialogForm
                                                            , onCaughtExceptionProcessAction
                                                        );
                                                }
                                                try
                                                {
                                                    onProcessedAction();
                                                }
                                                catch (Exception e)
                                                {
                                                    //r = -1;
                                                    onCaughtExceptionProcessAction(e);
                                                }
                                                finally
                                                {
                                                    TrySafeInvokeFormClose(dialogForm, onCaughtExceptionProcessAction);
                                                }
                                            }
                                    );
            Task.WaitAny(task1, task2);
            //DialogResult dialogResult = await task;
            return r;
        }
        public static int ProcessWaitingShowDialog
                            (
                                IWin32Window ownerWindow
                                , Form dialogForm
                                , Action onProcessAction = null
                                , Action onProcessedAction = null
                                , Action<Exception> onCaughtExceptionProcessAction = null
                            )
        {
            //var wait = new AutoResetEvent(false);
            int r = 1;
            if (onProcessAction != null)
            {
                new Thread
                        (
                            new ThreadStart
                                (
                                    () =>
                                    {
                                        //wait.WaitOne();
                                        Thread.Sleep(10);
                                        try
                                        {
                                            //
                                            onProcessAction();
                                            r = 0;
                                        }
                                        catch (Exception e)
                                        {
                                            r = -1;
                                            if (onCaughtExceptionProcessAction != null)
                                            {
                                                onCaughtExceptionProcessAction(e);
                                            }
                                        }
                                        finally
                                        {
                                            TrySafeInvokeFormClose
                                                (
                                                    dialogForm
                                                    , onCaughtExceptionProcessAction
                                                );
                                        }
                                        try
                                        {
                                            onProcessedAction();
                                        }
                                        catch (Exception e)
                                        {
                                            //r = -1;
                                            onCaughtExceptionProcessAction(e);
                                        }
                                        finally
                                        {
                                            TrySafeInvokeFormClose(dialogForm, onCaughtExceptionProcessAction);
                                        }
                                    }
                                )
                        ).Start();
                //wait.Set();
                if (r != 0)
                {
                    dialogForm.ShowDialog(ownerWindow);
                }
            }
            return r;
        }
        private static bool TrySafeInvokeFormClose
                                (
                                    Form dialogForm
                                    , Action<Exception> onCaughtExceptionProcessAction
                                )
        {
            bool r = false;
            try
            {
                if
                (
                    dialogForm.IsHandleCreated
                    && !dialogForm.IsDisposed
                )
                {
                    dialogForm.Invoke
                            (
                                new Action
                                    (
                                        () =>
                                        {
                                            //try
                                            {
                                                if
                                                (
                                                    dialogForm.IsHandleCreated
                                                    && !dialogForm.IsDisposed
                                                )
                                                {
                                                    dialogForm.Close();
                                                }
                                                //throw new Exception("理论上不应该被外侧 try catch 捕获?!?!?!?!?!");
                                            }
                                            ///                                            catch (Exception e)
                                            ///                                            {
                                            ///                                                r = false;
                                            ///                                                if (onCaughtExceptionProcessAction != null)
                                            ///                                                {
                                            ///                                                    onCaughtExceptionProcessAction(e);
                                            ///                                                }
                                            ///                                            }
                                        }
                                    )
                            );
                    Thread.Sleep(10);
                }
                r = true;
            }
            catch (Exception e)
            {
                r = false;
                if (onCaughtExceptionProcessAction != null)
                {
                    onCaughtExceptionProcessAction(e);
                }
            }
            return r;
        }
        public static int ProcessWaitingCancelable
                            (
                                Func<AutoResetEvent> onWaitFactoryFunc
                                , Action onProcessAction
                                , Action onProcessedAction
                                , Action<Exception> onCaughtExceptionProcessAction
                            )
        {
            var wait = onWaitFactoryFunc();
            return
                ProcessWaitingCancelable
                            (
                                wait
                                , onProcessAction
                                , onProcessedAction
                                , onCaughtExceptionProcessAction
                            );
        }
        public static int ProcessWaitingCancelable
                            (
                                AutoResetEvent wait
                                , Action onProcessAction
                                , Action onProcessedAction
                                , Action<Exception> onCaughtExceptionProcessAction
                            )
        {
            int r = 1; //Cancel
            new Thread
                    (
                        new ThreadStart
                                (
                                    () =>
                                    {
                                        try
                                        {
                                            onProcessAction();
                                            r = 0;
                                            onProcessedAction();
                                        }
                                        catch (Exception e)
                                        {
                                            r = -1;
                                            onCaughtExceptionProcessAction(e);
                                        }
                                        finally
                                        {
                                            wait.Set();
                                        }
                                    }
                                )
                    ).Start();
            wait.WaitOne();
            return r;
        }
    }
}
namespace Microshaoft
{
    using System;
    using System.Drawing;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Forms;
    public class ProcessWaitingCancelableDialog : Form
    {
        private IContainer components = null;
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        private void InitializeComponent()
        {
            button1 = new Button();
            SuspendLayout();
            //
            // button1
            //
            button1.DialogResult = DialogResult.Cancel;
            button1.Location = new Point(98, 158);
            button1.Name = "button1";
            button1.Size = new Size(75, 23);
            button1.TabIndex = 0;
            button1.Text = "取消(&C)";
            button1.UseVisualStyleBackColor = true;
            //
            // MainForm
            //
            AutoScaleDimensions = new SizeF(8F, 16F);
            AutoScaleMode = AutoScaleMode.Font;
            CancelButton = button1;
            ClientSize = new Size(282, 253);
            ControlBox = false;
            Controls.Add(button1);
            ///Name = "MainForm";
            ///Text = "MainForm";
            ResumeLayout(false);
        }
        private Button button1;
        public Button CancelWaitButton
        {
            get
            {
                return button1;
            }
        }
        public ProcessWaitingCancelableDialog()
        {
            InitializeComponent();
            button1.Click += button1_Click;
        }
        void button1_Click(object sender, EventArgs e)
        {
            button1.Click -= button1_Click;
            Close();
        }
    }
}

原文地址:https://www.cnblogs.com/Microshaoft/p/3271587.html