gpt4 book ai didi

c# - 当应用程序退出时,如何等待我的异步操作完成?

转载 作者:可可西里 更新时间:2023-11-01 08:25:36 24 4
gpt4 key购买 nike

如果用户执行删除项目等操作,它会立即从 UI 中删除它们,然后使用 TPL 在后台线程上将它们从数据库中删除。问题是,如果用户在后台线程结束之前退出应用程序,则该项目实际上不会被删除。

在关闭应用程序之前是否有等待异步操作完成的标准方法?

我的异步调用是这样的:

if (MyObjectList.Contains(obj)) MyObjectList.Remove(obj);
Task.Factory.StartNew(() => DAL<MyEntities>.DeleteObject(obj));

更新

这是我使用的最终代码。我很高兴看到它按预期工作,但如果我可以改进它,请告诉我。我还有很多东西要学:)

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);
}
}

当开始一个重要的后台任务时,我使用了这个语法:

var task = Task.Factory.StartNew(() => DAL<MyEntities>.DeleteObject(obj));
EventSystem.Publish<TaskStartedMessage>(new TaskStartedMessage(task));
await task;
EventSystem.Publish<TaskEndedMessage>(new TaskEndedMessage(task));

我为 await/async 使用 AsyncCTP,为事件系统使用 Microsoft Prism 的 EventAggregator

最佳答案

没有标准方法,但由于您在此处创建了一个特定任务,因此应该很容易将其放入列表并构建一些退出逻辑以等待该列表中的所有任务。

好的,一个示例。未经测试且不完整:

// 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);
}
}


缺点是您必须使用代码扩展每个任务以添加和删除它。

忘记 Remove() (例如,当异常发生时)将是一个(小的)内存泄漏。这不是太关键,除了使用 using() block 给代码增加负担之外,您还可以定期运行 Cleanup() 方法,该方法使用 HashSet.RemoveWhere() 来删除未运行的任务。

关于c# - 当应用程序退出时,如何等待我的异步操作完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8617058/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com