C#WPF退出应用程序,运行后台工作程序更新对话框

时间:2017-06-30 22:08:20

标签: c# wpf backgroundworker

我的问题类似于this one,我的代码设置几乎相同,只是我使用BackgroundWorker代替WorkflowRuntime。 (答案对我来说似乎不起作用)

过去我在Application.Current.Shutdown();的结束事件中使用了MainWindow,但是我希望通过正确处理这个我已经制作了静态资源的窗口我可能不会需要那个。

问题是,如果我在所有后台任务终止后通过关闭MainWindow退出,则空BackgroundDialog仍然打开。

public partial class BackgroundDialog : Window
{
    private static BackgroundDialog _Dialog = new BackgroundDialog();
    private static UIElementCollection TasksView { get { return _Dialog.BackgroundList.Children; } }

    public static void Add(BackgroundItem item)
    {
        if (TasksView.Count == 0)
        {
            _Dialog.Show();
        }
        TasksView.Add(item);
    }

    public static void Remove(BackgroundItem item)
    {
        TasksView.Remove(item);
        if (TasksView.Count == 0)
        {
            if (_Release)
            {
                FinishRelease();
            }
            else
            {
                _Dialog.Hide();
            }
        }
    }
    private static bool _Release = false;
    private static void FinishRelease()
    {
        // FinishRelease may be called from a BackgroundWorker thread finishing
        // This results in _Dialog.Close() not behaving as expected
        // For more details: https://stackoverflow.com/questions/5659930/wpf-window-not-closing
        _Dialog.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
        {
            _Dialog.Close();
            _Dialog = null;
        }));
    }

    public static void Release(EventArgs e)
    {
        _Release = true;
        if (TasksView.Count == 0)
        {
            FinishRelease();
        }
        else foreach (BackgroundItem Task in TasksView)
        {
            Task.Abort();
        }
    }
}

public partial class BackgroundItem : UserControl
{
    public delegate void TaskHandler(BackgroundWorker Worker);

    public interface IBackgroundTask
    {
        bool IsIndeterminate { get; }
        int MaxProgress { get; }
        string Title { get; }
        string Description(int progress);
        TaskHandler Exec { get; }
    }

    private BackgroundWorker Worker;

    public BackgroundItem(IBackgroundTask task)
    {
        InitializeComponent();

        Title.Text = task.Title;
        Description.Text = task.Description(0);

        Progress.Value = 0;
        Progress.Minimum = 0;
        Progress.Maximum = task.MaxProgress;
        Progress.IsIndeterminate = task.IsIndeterminate;

        BackgroundDialog.Add(this);

        Worker = new BackgroundWorker()
        {
            WorkerReportsProgress = true,
            WorkerSupportsCancellation = true,
        };
        Worker.DoWork += (object sender, DoWorkEventArgs e) =>
        {
            task.Exec?.Invoke(Worker);
        };
        Worker.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs e) =>
        {
            BackgroundDialog.Remove(this);
        };
        Worker.ProgressChanged += (object sender, ProgressChangedEventArgs e) =>
        {
            Progress.Value = e.ProgressPercentage;
            Description.Text = task.Description(e.ProgressPercentage);
        };
        Worker.RunWorkerAsync();

        Stop.Click += (object sender, RoutedEventArgs e) =>
        {
            Abort();
        };
    }

    public void Abort()
    {
        Worker.CancelAsync();
        Stop.IsEnabled = false;
        StopText.Text = "Stopping";
    }
}

public partial class MainWindow : Window
{
    private class MyTask : BackgroundItem.IBackgroundTask
    {
        public bool IsIndeterminate => true;
        public int MaxProgress => 100;
        public string Title => "I'm Counting";
        public BackgroundItem.TaskHandler Exec => (BackgroundWorker Worker) =>
        {
            for (int i = 0; i < 100; ++i)
            {
                if (Worker.CancellationPending)
                {
                    break;
                }
                Worker.ReportProgress(i);
                Thread.Sleep(500);
            }
        };

        public string Description(int progress)
        {
            return progress.ToString();
        }
    }

    public MainWindow()
    {
        InitializeComponent();

        Loaded += (object sender, RoutedEventArgs e) => {
            new BackgroundItem(new MyTask());
            new BackgroundItem(new MyTask());
            new BackgroundItem(new MyTask());
        };
    }

    protected override void OnClosed(System.EventArgs e)
    {
        base.OnClosed(e);
        BackgroundDialog.Release(e);
    }
}

2 个答案:

答案 0 :(得分:0)

尝试查看Application.ShutdownMode。您需要将ShutdownMode设置为OnMainWindowClose。

答案 1 :(得分:0)

我觉得很傻,一定是星期五结束了......这就是问题

BackgroundDialog中的

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    e.Cancel = true;
}

在我找到this解决方案之前,一定是遗物。但是,需要进行一些取消以防止用户从任务栏关闭对话框。所以我用声明if (!_Release)

包装了取消