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窗口
位于不同的项目中。如果我可以这样标记这个问题,我会把它搁置到