Rac*_*hel 12 c# wpf asynchronous task-parallel-library
如果用户执行操作(例如删除项目),则会立即将其从UI中删除,然后使用TPL在后台线程上将其从数据库中删除.问题是如果用户在后台线程完成之前退出应用程序,该项目实际上永远不会被删除.
在关闭应用程序之前是否存在等待异步操作完成的标准方法?
我的异步调用看起来像这样:
if (MyObjectList.Contains(obj)) MyObjectList.Remove(obj);
Task.Factory.StartNew(() => DAL<MyEntities>.DeleteObject(obj));
Run Code Online (Sandbox Code Playgroud)
更新
这是我最后的代码.我很高兴看到它能够正常工作,但是如果我能改进的话,请告诉我.我还有很多东西需要学习:)
public partial class App : Application
{
private List<Task> _backgroundTasks = new List<Task>();
public App()
{
EventSystem.Subscribe<TaskStartedMessage>((e) =>
{
_backgroundTasks.Add(e.Task);
});
EventSystem.Subscribe<TaskEndedMessage>((e) =>
{
if (_backgroundTasks.Contains(e.Task))
_backgroundTasks.Remove(e.Task);
});
}
protected override void OnExit(ExitEventArgs e)
{
Task.WaitAll(_backgroundTasks.Where(p => !p.IsCompleted).ToArray(), 30000);
base.OnExit(e);
}
}
Run Code Online (Sandbox Code Playgroud)
在开始一项重要的后台任务时,我正在使用以下语法:
var task = Task.Factory.StartNew(() => DAL<MyEntities>.DeleteObject(obj));
EventSystem.Publish<TaskStartedMessage>(new TaskStartedMessage(task));
await task;
EventSystem.Publish<TaskEndedMessage>(new TaskEndedMessage(task));
Run Code Online (Sandbox Code Playgroud)
我正在使用AsyncCTP for await/ async,而Microsoft Prism EventAggregator用于事件系统.
Hen*_*man 10
没有标准方法,但由于您在此处创建特定任务,因此应该很容易将其放入List中并构建一些Exit-logic以等待该List中的所有任务.
好的,样品.未经测试和不完整:
// untested
static class CriticalTasks
{
static HashSet<Task> tasks = new HashSet<Task>();
static object locker = new object();
// when starting a Task
public static void Add(Task t)
{
lock(locker)
tasks.Add(t);
}
// When a Tasks completes
public static void Remove(Task t)
{
lock(locker)
tasks.Remove(t);
}
// Having to call Remove() is not so convenient, this is a blunt solution.
// call it regularly
public static void Cleanup()
{
lock(locker)
tasks.RemoveWhere(t => t.Status != TaskStatus.Running);
}
// from Application.Exit() or similar.
public static void WaitOnExit()
{
// filter, I'm not sure if Wait() on a canceled|completed Task would be OK
var waitfor = tasks.Where(t => t.Status == TaskStatus.Running).ToArray();
Task.WaitAll(waitfor, 5000);
}
}
Run Code Online (Sandbox Code Playgroud)
缺点是您必须使用代码扩展每个任务以添加和删除它.
忘记Remove()(例如,当发生异常时)将是(小)内存泄漏.它不是太关键,using()你可以定期运行一个使用HashSet.RemoveWhere()删除非运行任务的Cleanup()方法,而不是用块加载你的代码.
| 归档时间: |
|
| 查看次数: |
5987 次 |
| 最近记录: |