Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#WPF正在退出应用程序,运行后台工作人员更新对话框_C#_Wpf_Backgroundworker - Fatal编程技术网

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

C#WPF正在退出应用程序,运行后台工作人员更新对话框,c#,wpf,backgroundworker,C#,Wpf,Backgroundworker,我的问题类似于,除了使用BackgroundWorker而不是WorkflowRuntime之外,我的代码设置基本相同。(答案似乎对我不起作用) 过去我使用过Application.Current.Shutdown()在关闭MainWindow的事件中,但是我希望通过正确地处理这个窗口(我已经创建了一个静态资源),我可能不需要它 问题是,如果在所有后台任务结束后通过关闭main窗口退出,则空的BackgroundDialog将保持打开状态 public partial class Backgro

我的问题类似于,除了使用
BackgroundWorker
而不是
WorkflowRuntime
之外,我的代码设置基本相同。(答案似乎对我不起作用)

过去我使用过
Application.Current.Shutdown()
在关闭
MainWindow
的事件中,但是我希望通过正确地处理这个窗口(我已经创建了一个静态资源),我可能不需要它

问题是,如果在所有后台任务结束后通过关闭
main窗口退出,则空的
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);
    }
}
公共部分类背景对话框:窗口
{
私有静态背景对话框_Dialog=新建背景对话框();
私有静态UIElementCollection任务视图{get{return}Dialog.BackgroundList.Children;}
公共静态无效添加(BackgroundItem)
{
如果(TasksView.Count==0)
{
_Dialog.Show();
}
TasksView.Add(项目);
}
公共静态无效删除(BackgroundItem)
{
任务视图。删除(项目);
如果(TasksView.Count==0)
{
如果(_发布)
{
FinishRelease();
}
其他的
{
_Dialog.Hide();
}
}
}
私有静态bool_Release=false;
私有静态void FinishRelease()
{
//FinishRelease可以从BackgroundWorker线程精加工调用
//这会导致_Dialog.Close()的行为不符合预期
//有关详细信息:https://stackoverflow.com/questions/5659930/wpf-window-not-closing
_Dialog.Dispatcher.Invoke(DispatcherPriority.Normal,新操作(()=>
{
_Dialog.Close();
_Dialog=null;
}));
}
公共静态无效释放(事件参数e)
{
_释放=真;
如果(TasksView.Count==0)
{
FinishRelease();
}
else foreach(TasksView中的BackgroundItem任务)
{
Task.Abort();
}
}
}
公共部分类背景项:UserControl
{
公共委托无效任务处理程序(后台工作人员);
公共接口IBackgroundTask
{
布尔值不确定{get;}
int MaxProgress{get;}
字符串标题{get;}
字符串描述(int进程);
TaskHandler执行程序{get;}
}
私人背景工人;
公共背景项(IBackgroundTask任务)
{
初始化组件();
Title.Text=task.Title;
Description.Text=task.Description(0);
进度值=0;
进度。最小值=0;
Progress.max=task.MaxProgress;
Progress.isindestime=task.isindestime;
BackgroundDialog.Add(这个);
Worker=新的BackgroundWorker()
{
WorkerReportsProgress=true,
WorkerSupportsScanCellation=true,
};
Worker.DoWork+=(对象发送方,doworkereventargs e)=>
{
task.Exec?.Invoke(Worker);
};
Worker.RunWorkerCompleted+=(对象发送方,RunWorkerCompletedEventArgs e)=>
{
背景对话框。删除(此);
};
Worker.ProgressChanged+=(对象发送方,ProgressChangedEventArgs e)=>
{
进度值=e.ProgressPercentage;
Description.Text=task.Description(如进度百分比);
};
Worker.RunWorkerAsync();
停止。单击+=(对象发送者,路由目标e)=>
{
中止();
};
}
公共无效中止()
{
Worker.CancelAsync();
Stop.IsEnabled=false;
StopText.Text=“停止”;
}
}
公共部分类主窗口:窗口
{
私有类MyTask:BackgroundItem.IBackgroundTask
{
公共布尔值IsIndeterminate=>true;
公共int MaxProgress=>100;
公共字符串标题=>“我正在计数”;
public BackgroundItem.TaskHandler Exec=>(BackgroundWorker Worker)=>
{
对于(int i=0;i<100;++i)
{
if(工作人员取消挂起)
{
打破
}
工人进度报告(一);
睡眠(500);
}
};
公共字符串描述(int进程)
{
返回progress.ToString();
}
}
公共主窗口()
{
初始化组件();
已加载+=(对象发送方,路由目标e)=>{
新的背景项(new MyTask());
新的背景项(new MyTask());
新的背景项(new MyTask());
};
}
关闭时受保护的覆盖无效(System.EventArgs e)
{
基础。一旦关闭(e);
背景对话。发布(e);
}
}

尝试查看。您需要将关机模式设置为OnMainWindowClose

我觉得很傻,一定是星期五那天结束了……问题出在这里

背景对话框中

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

一定是我找到解决办法之前的遗物。但是,需要进行一些取消操作,以防止用户从任务栏关闭对话框。因此,我用语句
if(!\u Release)

包装了cancel,这会导致应用程序在主窗口关闭时立即关闭,而不是给后台线程时间来完成对
CancellationPending
的响应。谢谢,但这是不需要的行为,Ori无法在家中的新项目中复制此行为,因此除了使用此代码的新wpf项目外,还必须进行其他操作。如果有帮助,则
BackgroundDialog
BackgroundItem
类与
main窗口
位于不同的项目中。如果我可以这样标记这个问题,我会把它搁置到