【问题标题】:How to make 2 tasks run simultaneously in a UWP background app?如何使 2 个任务在 UWP 后台应用程序中同时运行?
【发布时间】:2020-03-04 17:08:21
【问题描述】:

我需要帮助来运行部署在 Raspberry Pi(托管 Windows 10 IOT Core)上的 UWP 后台应用程序。

它几乎可以工作,但我遇到了一个棘手的问题......让我解释一下:

该应用有 2 个功能:

  • 一个Web Server,接收http请求,根据参数做一些处理。 (基于this link
  • 每 X 分钟执行一次的重复任务(X 从 10 到 60 不等)。

如果单独执行,这两个功能都可以很好地工作,但我需要它们同时运行。我对 UWP 和 Raspberry 比较陌生,所以也许我缺少一些东西......

  • 是线程冲突的问题吗?
  • 覆盆子上的后台任务是否仅限于单个线程(因此第一个/最后一个执行的进程获胜)?
  • 是否所有类都需要“密封”(微软的文档是这样说的,但他们提供的示例却没有)?

我坚持将项目分成两个独立的可部署任务,我相信它会起作用,但我需要网络服务器任务来控制(开始/暂停/停止)重复任务。

我认为他们之间的通信可能是可行的(使用this way),但我在这里寻找最简单/最快的解决方案。

这是精简后的代码(这 3 个类位于不同的文件中):

应用类:

public sealed class StartupTask : IBackgroundTask
{
    private static BackgroundTaskDeferral _Deferral = null;

    public async void Run(IBackgroundTaskInstance taskInstance)
    {
        _Deferral = taskInstance.GetDeferral();

        var webserver = new WebServer();
        await ThreadPool.RunAsync(workItem => { webserver.Start(); });

        StartRepeatingTask();
    }
}

Web 服务器类:

internal class WebServer
{
    private const uint BUFFER_SIZE = 8192;

    public async void Start()
    {
        var listener = new StreamSocketListener();
        await listener.BindServiceNameAsync("1537");

        listener.ConnectionReceived += async (sender, args) =>
        {
            // Do some stuff
            ...
            Processing.StopProcess();
        }
    }
}

处理类

public class Processing 
{
    private static Task myTask = null;
    private static CancellationTokenSource taskCancellation = new CancellationTokenSource();

    public static void StartRepeatingTask()
    {
        taskCancellation = new CancellationTokenSource();
        myTask = Task.Run(() => AutoProcess(), taskCancellation.Token);
    }

    public static void AutoProcess()
    {
        Process();

        myTask = Task.Delay(GetDelayToUse(DELAY_SET_LIST))
            .ContinueWith(t => AutoProcess(), taskCancellation.Token);
    }

    public static void Process()
    {
        // Do some other stuff
    }

    public static void StopProcess()
    {
        taskCancellation.Cancel();
    }
}

【问题讨论】:

    标签: c# uwp background raspberry-pi windows-iot-core-10


    【解决方案1】:

    这两个任务可以同时在后台应用程序中运行。

    是线程冲突的问题吗?

    如果两个任务之间没有提交或共享数据,则不会发生冲突。重要的是您需要注意数据的同步。如果使用列表或队列在两个线程之间共享数据,则应使用并发对象。请参考ConcurrentQueue的例子,ConcurrentQueue代表线程安全。

    树莓上的后台任务仅限于单个线程(因此 第一个/最后一个执行的进程获胜)?

    一旦部署和配置了后台应用程序,这些应用程序将在机器启动时启动并连续运行,而没有任何进程生命周期管理资源使用限制。后台任务有一些限制,但不限于单线程。更多信息here。这里需要区分 Windows IoT Core 上的background application 和任务。

    所有类都需要“密封”吗(微软的文档这么说但是 不是他们提供的例子)?

    是的,后台任务类本身——以及后台任务项目中的所有其他类——需要是密封(或最终)的公共类。它适用于继承自接口IBackgroundTask的后台任务,但不适用于普通线程使用的类。

    【讨论】:

    • 如果我没听错的话:“WebServer 任务”和“重复任务”可以从同一个后台应用程序启动,只有“StartupTask”必须是“公开密封的”。对?这就是我所做的,为什么两个任务不能同时工作?
    • 是的,你是对的。当 botch 任务开始运行时,您是否监控到异常?可能是某些异常导致任务退出,因此您可以看到两个任务不能同时工作。
    • @DonMadrino,我已经测试了代码,这两个任务同时工作。但我发现 AutoProcess 方法中有一个递归调用。你为什么这样做?我不确定递归调用中 Process 中的内容是否会导致问题。
    • 通过一些试验和错误禁用代码,我发现 ReadBlock 正在停止 Web 服务器;我的结论是垃圾收集器需要为它清理一些空间,所以它杀死了没有强引用的监听器实例。所以我将它添加到应用程序的属性(CoreApplication.Properties.Add("listener", listener))中,从那以后它似乎在几个小时后也能按预期工作!我会尝试更长时间的运行,看看它是否仍然有效。谢谢你的帮助! :-)
    猜你喜欢
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多